从构造函数的C ++虚函数

为什么下面的例子打印出“0”,而为了打印出“1”,我想要怎么改变呢?

#include <iostream> struct base { virtual const int value() const { return 0; } base() { std::cout << value() << std::endl; } virtual ~base() {} }; struct derived : public base { virtual const int value() const { return 1; } }; int main(void) { derived example; } 

由于base是首先构build,并没有“成熟”到derived 。 当不能保证对象已经正确初始化时,它不能调用对象上的方法。

在构造派生对象时,在派生类构造函数的主体被调用之前,基类构造函数必须完成。 在调用派生类构造函数之前,正在构build的对象的dynamictypes是基类实例,而不是派生类实例。 因此,当从构造函数调用虚函数时,只能调用基类虚函数覆盖。

事实上,有一种方法来获得这种行为。 “软件中的每一个问题都可以通过一种间接的方式来解决。”

 /* Disclaimer: I haven't done C++ in many months now, there might be a few syntax errors here and there. */ class parent { public: parent( ) { /* nothing interesting here. */ }; protected: struct parent_virtual { virtual void do_something( ) { cout << "in parent."; } }; parent( const parent_virtual& obj ) { obj.do_something( ); } }; class child : public parent { protected: struct child_virtual : public parent_virtual { void do_something( ) { cout << "in child."; } }; public: child( ) : parent( child_virtual( ) ) { } }; 

你不应该多态地从构造函数中调用虚拟方法。 相反,您可以在构build对象后调用它们。

你的代码可以被重写如下

 struct base { virtual const int value() const { return 0; } base() { /* std::cout << value() << std::endl; */ } virtual ~base() {} }; struct derived : public base { virtual const int value() const { return 1; } }; int main(void) { derived example; std::cout << example.value() << std::endl; } 

如何工作的问题是一个FAQ项目

总结一下,在构造类T同时,dynamictypes是T ,它阻止对派生类函数实现的虚拟调用,如果允许的话,可以在相关的类不variables已经build立之前执行代码(在Java和C#中的常见问题,但是C ++在这方面是安全的)。

在基类构造函数中如何做派生类特定的初始化的问题也是一个FAQ项目 ,直接跟在前面提到的一个。

总结一下,使用静态或dynamic多态性可能会将相关函数实现传递给基类构造函数(或类)。

一个特别的方法就是通过一个“零件工厂”的对象 ,这个参数可以被默认。 例如,一个普通的Button类可能会将一个button创buildAPI函数传递给它的Widget基类的构造函数,这样这个构造函数就可以创build正确的API级别的对象。

一般的规则是你不要从构造函数中调用虚函数。

在C ++中,您不能从构造函数调用虚拟/重写方法。

现在,有一个很好的理由可以做到这一点。 作为“软件中的最佳实践”,应尽可能避免从构造函数中调用其他方法,即使是非虚拟方法。

但是,规则总是有一个例外,因此您可能需要使用“伪构造方法”来模拟它们:

 #include <iostream> class base { // <constructor> base() { // do nothing in purpouse } // </constructor> // <destructor> ~base() { // do nothing in purpouse } // </destructor> // <fake-constructor> public virtual void create() { // move code from static constructor to fake constructor std::cout << value() << std::endl; } // </fake-constructor> // <fake-destructor> public virtual void destroy() { // move code from static destructor to fake destructor // ... } // </fake-destructor> public virtual const int value() const { return 0; } public virtual void DoSomething() { // std:cout << "Hello World"; } }; class derived : public base { // <fake-constructor> public override void create() { // move code from static constructor to fake constructor std::cout << "Im pretending to be a virtual constructor," << std::endl; std::cout << "and can call virtual methods" << std::endl; } // </fake-constructor> // <fake-destructor> public override void destroy() { // move code from static destructor to fake destructor std::cout << "Im pretending to be a virtual destructor," << std::endl; std::cout << "and can call virtual methods" << std::endl; } // </fake-destructor> public virtual const int value() const { return 1; } }; int main(void) { // call fake virtual constructor in same line, after real constructor derived* example = new example(); example->create(); // do several stuff with your objects example->doSomething(); // call fake virtual destructor in same line, before real destructor example->destroy(); delete example(); } 

另外,我build议程序员只使用“struct”字段结构,而“class”使用字段,方法,构造函数等等。