我在类层次结构中遇到了一个问题,到目前为止我无法解决。下面是一个最小的例子,其中模板Base
类本身继承自另一个不是模板的类(在下面的例子中称为AbsoluteBase
)。然后,类Derived
继承自Base
,其模板参数也是Bases'
模板参数:
#include <iostream>
using namespace std;
class AbsolutBase {
protected:
int number;
AbsoluteBase(int _number) {
number = _number;
}
virtual ~AbsoluteBase() {}
virtual void print() const = 0;
};
template <typename T> class Base : virtual public AbsoluteBase {
public:
Base(int _number) : AbsoluteBase(_number) {}
virtual void print() const {
cout << number << endl;
}
};
template <typename T> class Derived : public Base<T> {
public:
Derived(int _number) : Base<T>::Base(_number) {}
};
int main() {
Derived<char> object(100);
object.print();
}
因此每个构造函数都调用其父构造函数,并将一个整数作为参数传递给AbsoluteBase
。但是在编译代码时我得到了:
error: no matching function for call to 'AbsoluteBase::AbsoluteBase()'
note: candidates are: AbsoluteBase::AbsoluteBase(int)
note: candidate expects 1 argument, 0 provided
使Base
的实例工作正常但在Derived
的初始化列表中调用其构造函数时,编译器希望AbsolutBase()
作为构造函数,即使给出了整数参数。显然,在AbsoluteBase
中定义默认构造函数时,print()
函数会输出garbage,因为没有值传递给number
。
因此我对Base<T>::Base(int)
的呼吁有些不对劲,但我无法看到它是什么。我很感激每一个解释和帮助!
问候, Benniczek
答案 0 :(得分:1)
AbsoluteBase
是一个虚拟基类。因此,必须由最派生类的构造函数初始化。您的初始值设定项AbsoluteBase(_number)
有效,但只有在直接实例化Base<T>
类型的对象时才会使用它。
最好的解决方案可能不是让AbsoluteBase
成为虚拟基类。
此规则的原因是:
class Silly: public Base<int>, Base<long>
{
public:
Silly() : Base<int>::Base(1), Base<long>::Base(2) {}
};
只有一个AbsoluteDerived
对象(在此上下文中是virtual
的含义),它是用1还是2初始化的?
答案 1 :(得分:0)
您在没有e的情况下将Absolute Base声明为class AbsolutBase
。用错字修复编译就好了。
编辑:如果您有从Absolute进行虚拟继承的类库,它也将无法编译。除非您需要虚拟继承(使用多重继承?),否则可以将其声明为类Base : public AbsoluteBase
如果确实需要虚拟继承(钻石问题),则需要在Derived类中初始化AbsoluteBase。鉴于Base实际上继承自AbsoluteBase,Derived也可以从Base2继承,它也实际上从AbsoluteBase继承(这是虚拟继承的一点,一个类可以从两个不同的类继承,它们本身从一个公共基础继承)。由于它是一个虚拟继承,即使Base和Base2可以从AbsoluteBase继承,也只能有一个AbsoluteBase,那么它是如何初始化的呢?这就是Derived需要直接初始化它的原因,这样当制作一份AbsoluteBase时,就可以很好地理解它是如何被初始化的。
同样,这很麻烦,如果你不需要虚拟继承(你可能不会猜测......)你可以公开地从AbsoluteBase继承Base并称之为一天。
答案 2 :(得分:0)
由于虚拟继承。当base
类从另一个类继承虚拟时,base
的子类还必须调用其父级的虚拟父级的构造函数。由于你没有这样做,编译器试图调用无参数AbsoluteBase的ctor。所以你只需编写如下代码:
template <typename T> class Derived : public Base<T> {
public:
Derived(int _number) : AbsoluteBase(_number), Base<T>::Base(_number) {}
};