我正在嘗試創建一個功能繼承層次結構。我們正在努力實作我們自己的優先佇列類模板,該程式包括購買訂單等串列。
我的想法是把“p_queue”作為基類,讓“orders”類繼承自它,然后讓“buy_orders”等子類繼承自orders類。我的理由是這個程式中的每個訂單都是一個優先佇列,因為它們將按它排序。
如果派生類沒有直接繼承超類,通常我會理解錯誤“型別'base_class'不是'sub_class'的直接基礎”。但由于訂單類繼承了 p_queue 類,而沒有其他類直接繼承自優先佇列類,我很困惑為什么會收到此錯誤訊息。
這是代碼
//main.cpp
#include "orders.h"
int main(){
return 0;
}
//orders.h
#include "p_queue.h"
template<typename T>
struct less{
bool operator()(const T& a, const T& b){
return a < b;
}
};
template<typename T>
class Orders : public p_queue<T, decltype(less<T>())> {
private:
size_t m_Size;
std::vector<T> list;
public:
Orders(const size_t& sz, const std::vector<T>& l) : list(l), m_Size(sz),
p_queue<T>(&(*list.begin()), &(*list.end()), less<T>()){}
virtual const size_t getSize() const { return m_Size; }
virtual const std::vector<T> getList() const = 0;
};
struct buy_orders : public Orders<size_t>{
std::vector<size_t> buy_prices;
buy_orders(const size_t& sz) : Orders(sz, buy_prices) {}
};
//p_queue.h
#include <functional>
template<typename T, typename Compare = std::less<T>>
class p_queue{
protected:
T* m_first;
T* m_last;
Compare m_comp;
public:
p_queue(T* first, T* last, Compare comp = Compare()) :
m_first(first), m_last(last), m_comp(comp) {}
};
上面的代碼產生錯誤:
<source>: In instantiation of 'Orders<T>::Orders(const size_t&, const std::vector<T>&) [with T = long unsigned int; size_t = long unsigned int]':
<source>:39:57: required from here
<source>:31:59: error: type 'p_queue<long unsigned int, std::less<long unsigned int> >' is not a direct base of 'Orders<long unsigned int>'
31 | p_queue<T>(&(*list.begin()), &(*list.end()), less<T>()){}
| ^
<source>:31:59: error: no matching function for call to 'p_queue<long unsigned int, less<long unsigned int> >::p_queue()'
<source>:13:5: note: candidate: 'p_queue<T, Compare>::p_queue(T*, T*, Compare) [with T = long unsigned int; Compare = less<long unsigned int>]'
13 | p_queue(T* first, T* last, Compare comp = Compare()) :
| ^~~~~~~
<source>:13:5: note: candidate expects 3 arguments, 0 provided
<source>:7:7: note: candidate: 'constexpr p_queue<long unsigned int, less<long unsigned int> >::p_queue(const p_queue<long unsigned int, less<long unsigned int> >&)'
7 | class p_queue{
| ^~~~~~~
<source>:7:7: note: candidate expects 1 argument, 0 provided
<source>:7:7: note: candidate: 'constexpr p_queue<long unsigned int, less<long unsigned int> >::p_queue(p_queue<long unsigned int, less<long unsigned int> >&&)'
<source>:7:7: note: candidate expects 1 argument, 0 provided
ASM generation compiler returned: 1
<source>: In instantiation of 'Orders<T>::Orders(const size_t&, const std::vector<T>&) [with T = long unsigned int; size_t = long unsigned int]':
<source>:39:57: required from here
<source>:31:59: error: type 'p_queue<long unsigned int, std::less<long unsigned int> >' is not a direct base of 'Orders<long unsigned int>'
31 | p_queue<T>(&(*list.begin()), &(*list.end()), less<T>()){}
| ^
<source>:31:59: error: no matching function for call to 'p_queue<long unsigned int, less<long unsigned int> >::p_queue()'
<source>:13:5: note: candidate: 'p_queue<T, Compare>::p_queue(T*, T*, Compare) [with T = long unsigned int; Compare = less<long unsigned int>]'
13 | p_queue(T* first, T* last, Compare comp = Compare()) :
| ^~~~~~~
<source>:13:5: note: candidate expects 3 arguments, 0 provided
<source>:7:7: note: candidate: 'constexpr p_queue<long unsigned int, less<long unsigned int> >::p_queue(const p_queue<long unsigned int, less<long unsigned int> >&)'
7 | class p_queue{
| ^~~~~~~
<source>:7:7: note: candidate expects 1 argument, 0 provided
<source>:7:7: note: candidate: 'constexpr p_queue<long unsigned int, less<long unsigned int> >::p_queue(p_queue<long unsigned int, less<long unsigned int> >&&)'
<source>:7:7: note: candidate expects 1 argument, 0 provided
如果我從 orders.h 中洗掉 buy_orders 結構,問題就會消失。為什么是這樣?我該如何解決這個問題?
uj5u.com熱心網友回復:
你實際上有兩個問題。
第一個很簡單,您必須將第二個模板引數顯式傳遞給p_queue建構式:
...
Orders(const size_t& sz, const std::vector<T>& l) : list(l), m_Size(sz),
p_queue<T, decltype(less<T>())>(&(*list.begin()), &(*list.end()), less<T>()) {}
...
足以使type 'base_class' is not a direct base of 'sub_class'錯誤消失。
但是還有另一個問題,即使它只是發出警告。在 C 中,無論初始化程式的順序如何,基類都在資料成員之前初始化。這意味著p_queue建構式將在 的初始化之前被呼叫list,從而導致未定義的行為,因為它在有機會被初始化之前顯式地使用了firstand成員。last這意味著您必須設定 2 個階段的初始化p_queue,首先使用默認初始化,然后在建構式主體m_first中設定其和m_last成員:Orders
...
p_queue(Compare comp = Compare()) : m_comp(comp) {}
p_queue(T* first, T* last, Compare comp = Compare()) :
m_first(first), m_last(last), m_comp(comp) {}
...
和
...
Orders(const size_t& sz, const std::vector<T>& l) : list(l), m_Size(sz),
p_queue<T, decltype(less<T>())>(less<T>()) {
this->m_first = &(*list.begin());
this->m_last = &(*list.end());
}
...
uj5u.com熱心網友回復:
問題 1
問題是p_queue<T>andp_queue<T, decltype(::less<T>())>是兩種不同的型別別,你從后者(p_queue<T, decltype(::less<T>())>)繼承,但試圖p_queue<T>在成員初始化串列中使用前者()的建構式。
要解決這個問題,只需確保在成員初始化串列中使用建構式p_queue<T, decltype(::less<T>())>而不是,p_queue<T>如下所示:
template<typename T>
class Orders : public p_queue<T, decltype(::less<T>())> {
private:
size_t m_Size;
std::vector<T> list;
public:
Orders(const size_t& sz, const std::vector<T>& l) : list(l), m_Size(sz),
//--------------vvvvvvvvvvvvvvvvvvvv---->added this second template argument
p_queue<T , decltype(::less<T>())>(&(*list.begin()), &(*list.end()), ::less<T>()){}
virtual const size_t getSize() const { return m_Size; }
virtual const std::vector<T> getList() const = 0;
};
作業演示
問題 2
此外,在初始化派生類成員 like 之前將使用基類 ctor list,并且由于您將其*list.begin()用作基類 ctor 的引數,因此程式具有未定義的行為。
Clang對此給出警告:
<source>:36:43: warning: field 'list' is uninitialized when used here [-Wuninitialized]
p_queue<T , decltype(::less<T>())>(&(*list.begin()), &(*list.end()), ::less<T>()){}
^
<source>:44:36: note: in instantiation of member function 'Orders<unsigned long>::Orders' requested here
buy_orders(const size_t& sz) : Orders(sz, buy_prices) {}
^
<source>:36:61: warning: field 'list' is uninitialized when used here [-Wuninitialized]
p_queue<T , decltype(::less<T>())>(&(*list.begin()), &(*list.end()), ::less<T>()){}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/519737.html
標籤:C 模板遗产
上一篇:實作細節繼承?
