我对构建使用继承的类的方式有疑问。在下面的示例中,对Base
构造函数的调用依赖于Derived
类中实现的函数。此函数再次依赖于Derived
成员generator
,该成员在Base
构造函数调用之后才会初始化。
如果首先构造Base
类,变量Base::in_
不会包含垃圾数据吗?
class Derived
: public Base
{
Derived()
: Base(get_data()),
generator(5) {}
Generator generator;
int get_data() { return generator.get_some_data(); }
};
class Base
{
Base(int in)
: in_(in) {}
int in_;
}
答案 0 :(得分:2)
首先,代码中没有任何内容是多态的。多态性是关于虚函数的。
接下来,您的类 Base
完全不依赖。在class Base {
和匹配的}
之间查看,那里的任何内容都不依赖于任何外部。
Base
中Derived
子对象的构造取决于Derived的另一个成员,该成员是在Base
之后构建的。您的分析基本上是正确的,这是一个真正的问题,需要通过重构您的课程来解决。
最简单的方法是Base的两阶段初始化(以下是伪代码,可能无法编译):
class Base {
Base(int in = 0) : in_(in) {}
void set(int in) { in_ = in; }
int in_;
};
class Derived : public Base {
Derived() : Base(), generator(5) {
Base::set(generator);
}
...
};
另一种方法是将依赖项移动到另一个基类:
class Base2 { ... generator implemented here ... };
class Derived : public Base2, public Base {
Derived() : Base2(5), Base(Base2::generator) {}
};
答案 1 :(得分:0)
我不知道标准说的是什么,但这显然是generator
调用get_data()
时的价值问题,因为如果你从其他地方调用它的话会是这样的构造函数。
从构造函数中调用的代码与其他代码没有任何不同。
我的猜测是在构造生成器之前调用get_data(),因此在运行时会得到一个NULL异常
另一点需要提及的是,基类当然是首先构建的。它是基类。 Derived
是一个Base
,它有一个字段in_
。
根据经验,它始终是一个很好的模式:
您还可以在get_data
中对Base
进行抽象,然后在Init()
Base
内调用它,这将是实现对子类的依赖的正确方法正如你所说的那样。
class Derived
: public Base
{
Derived()
: Base(),
generator(5) {}
Generator generator;
virtual int get_data() { return generator.get_some_data(); }
};
class Base
{
Base()
{
}
Init() {
in_ = get_data();}
int in_;
virtual int get_data() = 0;
}
答案 2 :(得分:0)
请参阅Order of calling constructors/destructors in inheritance
在初始化Derived的任何成员之前,将调用Base的构造函数。所以当调用get_data()时,生成器不会被初始化。
基本上,Base将使用垃圾进行初始化。