在 C++ 中使用多态性进行初始化的预期行为是什么?

Jim*_*ans 2 c++ polymorphism

这应该是一个简单的 100 级问题,但我在我的项目中看到了一些我没有想到的东西,并且网络搜索失败了,所以我想我应该在这里问。假设我有以下 C++ 代码:

class BaseClass {
public:
  BaseClass() { 
    this->Initialize(); 
  }

  int foo() {
    return this->foo_;
  }

protected:
  virtual int GetInitialValue() { 
    return 1; 
  }

private:
  void Initialize() {
    this->foo_ = this->GetInitialValue();
  }

  int foo_;
};

class DerivedClass : public BaseClass {
public:
  DerivedClass() : BaseClass() {
  }

protected:
  virtual int GetInitialValue() { 
    return 2; 
  }
};
Run Code Online (Sandbox Code Playgroud)

的返回值应该是多少DerivedClass::foo()?会BaseClass::GetInitialValue()被叫到吗,还是永远都会DerivedClass::GetInitialValue()被叫到?我应该在哪里搜索,应该使用哪些搜索词来找到答案?

wkl*_*wkl 5

GetInitialValue()不是虚拟的,所以无论如何也不存在动态调度。

在您的情况下, 的预期值为foo()1因为 的值_foo是在构造函数中设置的BaseClass。派生类的版本不会被调用,因为BaseClass首先调用构造函数,并且DerivedClass成员尚未初始化。

这也是《Effective C++》中的第 9 项,该片段位于 artima 的此页面中:

http://www.artima.com/cppsource/nevercall.html

该文章的摘要是:

要记住的事情

在构造或析构期间不要调用虚函数,因为此类调用永远不会转到比当前执行的构造函数或析构函数更派生的类

#include <iostream>

class Base {
   public:
   Base() { this->initialize(); }
   void initialize() { this->_foo = this->getInitial(); }
   virtual int getInitial() { return 1; }

   int _foo;
};

class Derived : public Base {
   public:
      Derived() : Base() {}
      virtual int getInitial() { return 2;}
};


int main()
{
   Base* dp = new Derived();
   std::cout << dp->_foo << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这段代码输出1.