【问题标题】:Assign Derived class Constructor to Base class Pointer将派生类构造函数分配给基类指针
【发布时间】:2016-08-02 17:37:39
【问题描述】:

我试图理解虚函数,并遇到了以下代码。

class Base
{
  public:
            void Method1 ()  {  std::cout << "Base::Method1" << std::endl;  }
    virtual void Method2 ()  {  std::cout << "Base::Method2" << std::endl;  }
};

class Derived : public Base
{
  public:
    void Method1 ()  {  std::cout << "Derived::Method1" << std::endl;  }
    void Method2 ()  {  std::cout << "Derived::Method2" << std::endl;  }
};

Base* obj = new Derived ();
  //  Note - constructed as Derived, but pointer stored as Base*

obj->Method1 ();  //  Prints "Base::Method1"
obj->Method2 ();  //  Prints "Derived::Method2"

最后,如何使用派生类构造函数初始化基类指针?

【问题讨论】:

标签: c++ pointers inheritance constructor


【解决方案1】:

C++ 允许从派生指针类型隐式转换为基指针类型。这是安全的,因为派生类型的内存布局与基类的大小相同。

您的示例有一个潜在的错误,因为您忘记了obj 的真实类型。当需要删除它时,您将调用错误的析构函数。这可以通过将析构函数设为虚拟来解决。

【讨论】:

    【解决方案2】:

    它被构造函数调用的结果初始化。 调用 new Derived() 会创建一个指向新 Derived 对象的指针。 并且由于类 Derived 是从类 Base 公开派生的,因此指向的新对象是基类(同时也是派生类)。

    【讨论】:

      【解决方案3】:

      对于表达式……

      obj->Method1 ();  //  Prints "Base::Method1"
      

      …编译器看到一个指向Base的实例对象的指针。它查找名为Method1 的方法。它发现它是一个 non-virtual 方法。所以它静态绑定它(也就是在编译时)并生成“直接”调用Base::Method1的代码。

      对于表达式……

      obj->Method2 ();  
      

      ...编译器看到一个指向Base 实例对象的指针。它查找名为Method2 的方法。它发现它是一个 virtual 方法。所以它不会静态绑定它(也就是在编译时),而是生成代码用于在obj 指向的实例对象的真实类上查找runtime。在运行时,有一个Derived 的实例对象。因此Derived::Method2会被找到并执行。

      让我们用伟大的艾伦凯的话来总结一下:

      实际上,“面向对象”这个词是我编出来的,我可以告诉你,我并没有想到 C++。

      【讨论】:

        猜你喜欢
        • 2021-09-09
        • 2021-06-25
        • 1970-01-01
        • 2017-08-02
        • 2020-09-06
        • 1970-01-01
        • 1970-01-01
        • 2023-03-22
        • 1970-01-01
        相关资源
        最近更新 更多