C++ 将派生类构造函数分配给基类指针

C++ 将派生类构造函数分配给基类指针,c++,pointers,inheritance,constructor,C++,Pointers,Inheritance,Constructor,我试图理解虚拟函数,遇到了以下代码 class Base { public: void Method1 () { std::cout << "Base::Method1" << std::endl; } virtual void Method2 () { std::cout << "Base::Method2" << std::endl; } }; class Derived : public Ba

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

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"
类基
{
公众:

void Method1(){std::cout将使用调用构造函数的结果初始化它。 调用new-Derived()创建指向新派生对象的指针。
由于类派生是从类基公开派生的,所以指向的新对象是一个基(同时也是派生对象)。

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

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


但是,您的示例有一个潜在的错误,因为您已经失去了对
obj
的真实类型的跟踪。当需要删除它时,您将调用错误的析构函数。这可以通过使析构函数虚拟来弥补。

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

但是,您的示例有一个潜在的错误,因为您已经失去了对
obj
的实际类型的跟踪。当需要删除它时,您将调用错误的析构函数。这可以通过使析构函数虚拟来弥补。

对于表达式

obj->Method1 ();  //  Prints "Base::Method1"
obj->Method2 ();  
…编译器看到一个指向
Base
实例对象的指针。它查找一个名为
Method1
的方法。它发现它是一个非虚拟方法。因此它静态绑定它(即在编译时),并生成“直接”调用
Base::Method1
的代码

对于表达式

obj->Method1 ();  //  Prints "Base::Method1"
obj->Method2 ();  
…编译器看到一个指向
Base
实例对象的指针。它查找一个名为
Method2
的方法。它发现它是一个虚拟方法。因此它不会静态绑定它(也称为编译时绑定),但生成运行时查找实例对象的实际类的代码。
obj
指向。在运行时,存在一个
Derived
的实例对象。因此,将找到并执行
Derived::Method2

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

实际上,我提出了“面向对象”一词,我可以告诉你我没有C++。
obj->Method1 ();  //  Prints "Base::Method1"
obj->Method2 ();  
…编译器看到一个指向
Base
实例对象的指针。它查找一个名为
Method1
的方法。它发现它是一个非虚拟方法。因此它静态绑定它(即在编译时),并生成“直接”调用
Base::Method1
的代码

对于表达式

obj->Method1 ();  //  Prints "Base::Method1"
obj->Method2 ();  
…编译器看到一个指向
Base
实例对象的指针。它查找一个名为
Method2
的方法。它发现它是一个虚拟方法。因此它不会静态绑定它(也称为编译时绑定),但生成运行时查找实例对象的实际类的代码。
obj
指向。在运行时,存在一个
Derived
的实例对象。因此,将找到并执行
Derived::Method2

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

实际上,我提出了“面向对象”一词,我可以告诉你我没有C++。