C++ 从基类构造函数调用派生类的成员函数

C++ 从基类构造函数调用派生类的成员函数,c++,inheritance,C++,Inheritance,如果我有 struct C { C() { init(); }; void init() { cout << "C" << endl; }; }; struct D : public C { D() : C() { }; void init() { cout << "D" << endl; } }; D(); struct C{ C(){init();}; void init(){cout您只能从C构造函数中删除ini

如果我有

struct C {
   C() { init(); };
   void init() { cout << "C" << endl; };
};

struct D : public C {
   D() : C() { };
   void init() { cout << "D" << endl; }
};

D();
struct C{
C(){init();};

void init(){cout您只能从C构造函数中删除
init()
,以不打印“C”。 要同时打印“D”,请在
D()
构造函数中添加
init()

如果在某些情况下,您需要打印“C”或“D”,而在某些情况下,您不需要这样做

struct C {
   C() { };
   void init() { cout << "C" << endl; };
};

struct D : public C {
   D() : C() 
   { 
     if(some condition)
       C::init();

     if(some condition)
       init();
   };

   void init() { cout << "D" << endl; }
};

D();
struct C{
C(){};
void init(){cout
为什么要打印“C”

C::init()
未声明为
virtual
,因此
D
无法重写它。但是,即使
C::init()
声明为
virtual
,在
C
的构造函数内部调用
init
)时仍不会调用
D::init()

C++在派生类之前构造基类(并且在基类之前分解派生类)。因此
C
的构造函数在
D
被构造之前运行(而
C
的析构函数在
D
被分解之后运行).正在构造/破坏的对象的VMT根本不指向
D
的方法表当
C
正在构造/破坏时,它指向
C
的方法表

如何改变这种行为(并获得“D”)


无法从基类构造函数/析构函数内部调用派生虚拟方法。在这些阶段,VMT不包含指向派生类方法表的指针。

这里有一个非常基本的问题:您希望在一个尚不存在的对象上调用派生类的成员函数

请记住,对象是通过先构造基本子对象,然后再构造派生对象来构造的。因此,即使您成功地应用了“聪明的”实际上调用派生类'
init
函数的技巧,一旦该函数试图访问派生对象的任何数据成员,就会造成任意损坏。另一方面,只要不依赖构造函数尚未建立的任何不变量,就可以只访问基对象。因此或者,如果您不需要访问派生对象的数据,您可以使
init
函数
static
并将其传递给基类对象的引用

也许这正接近你想要做的

#include <iostream>

struct Base
{
  Base(void (*fp)(Base&) = Base::init) { fp(*this); }
  static void init(Base&) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

struct Derived : Base
{
  Derived() : Base(Derived::init) { }
  static void init(Base&) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

int
main()
{
  Base b {};
  std::cout << std::endl;
  Derived d {};
}
在这里,基类构造函数采用一个函数指针,指向引用
base
对象的初始值设定函数。该函数默认为
base::init
,但派生类可以替换它。但是,请注意,在这种设计中,
base
类构造函数可能无法安全地假定实际上,
Base::init
的ct已经发生了。不过,作为一种扩展机制(如果
Base::init
什么都不做或者是一次性的),它是很好的

<>但是我怀疑你是否需要使用这类机器。如果你想做的事情——这应该是正常的情况——首先初始化基础对象,然后是派生对象,如果你简单地调用来自各个构造函数的函数,C++将已经做正确的事情。

struct Base
{
  Base() { this->init(); }
  void init() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

struct Derived : Base
{
  Derived() { this->init(); }
  void init() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

// main() as above ...
如果我们只想调用最派生的类'
init
函数,我们可以简单地告诉基类不要运行自己的类

struct Base
{
  Base(const bool initialize = true) { if (initialize) this->init(); }
  void init() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

struct Derived : Base
{
  Derived() : Base(false) { this->init(); }
  void init() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

// main() as above ...

即使
init
virtual
(我假设这是您想要实现的),从构造函数中调用
virtual
函数也不是一个很好的主意这是一个公然反对多态性的案例。@DanielKamilKozar该类不是多态性的(没有任何虚拟函数)@MattMcNabb:当然。但是,看到OP的代码和预期结果,有理由认为使用多态性是他的意图之一。