C++ 运行时多态性中的构造函数行为

C++ 运行时多态性中的构造函数行为,c++,C++,我们知道需要一个虚拟析构函数 Base *bptr = new Derived(); delete bptr; 如果派生类对象由基类指针指向,并且当对象超出范围时,只有基类析构函数被调用,除非析构函数是虚拟的 我想知道在这种情况下构造函数是如何正常工作的。 因为基指针指向派生对象,所以应该只调用基构造函数。如何正确调用派生类构造函数 请向我解释这背后的原因。new-Derived()在任何地方都没有基类引用。您甚至可以选择不指定它。因此,结果指针的赋值不会影响构造。new-Derived()在

我们知道需要一个虚拟析构函数

Base *bptr = new Derived();
delete bptr;

如果派生类对象由基类指针指向,并且当对象超出范围时,只有基类析构函数被调用,除非析构函数是虚拟的

我想知道在这种情况下构造函数是如何正常工作的。 因为基指针指向派生对象,所以应该只调用基构造函数。如何正确调用派生类构造函数


请向我解释这背后的原因。

new-Derived()在任何地方都没有基类引用。您甚至可以选择不指定它。因此,结果指针的赋值不会影响构造。

new-Derived()在任何地方都没有基类引用。您甚至可以选择不指定它。因此,结果指针的赋值不会影响构造。

执行以下操作时:

Base *bptr = new Derived();
您正在为
派生的
类调用
新的
操作符,因为这就是您要构造的


当您将
new
返回的
Derived*
分配给
Base*
时,您只需向上投射作为隐式操作的指针。

当您执行以下操作时:

Base *bptr = new Derived();
您正在为
派生的
类调用
新的
操作符,因为这就是您要构造的


当您将
new
返回的
Derived*
分配给
Base*
时,您只需向上投射指针,这是一个隐式操作。

使用
new
创建对象时,我们拥有对象的完整信息

new Derived(); // static type is same as dynamic type
指定指针的LHS部分是不相关的。这就是为什么构造函数不需要这种
虚拟
机制的原因。有关详细信息,请参阅的页面

另外,需要使用
virtual
析构函数,因为您使用的是指向
delete
对象的指针

delete bptr; // static type may not be same as dynamic type

使用
new
创建对象时,我们拥有对象的完整信息

new Derived(); // static type is same as dynamic type
指定指针的LHS部分是不相关的。这就是为什么构造函数不需要这种
虚拟
机制的原因。有关详细信息,请参阅的页面

另外,需要使用
virtual
析构函数,因为您使用的是指向
delete
对象的指针

delete bptr; // static type may not be same as dynamic type
明确地说您想要构造一个
派生的
实例:

Base *bptr = new Derived();
表示如果类型为
派生类
,请构造一个对象,然后请在
bptr
中存储指向该对象的指针。因此编译器没有任何东西可以猜测或推断

将其与:

new Derived();
它创建一个
类派生的
对象并泄漏该对象。编译器在这里也没有什么可以猜测或推断的。这两个代码段之间的唯一区别是前者存储指针,而后者不存储。

明确地说,您想要构造一个
派生的
实例:

Base *bptr = new Derived();
表示如果类型为
派生类
,请构造一个对象,然后请在
bptr
中存储指向该对象的指针。因此编译器没有任何东西可以猜测或推断

将其与:

new Derived();

它创建一个
类派生的
对象并泄漏该对象。编译器在这里也没有什么可以猜测或推断的。这两个代码段之间的唯一区别是前者存储指针,而后者不存储。

“如果派生类对象由基类指针指向,并且当对象超出范围时,只有基类析构函数被调用,除非析构函数是虚拟的。”-如果派生类的对象超出范围,调用派生类析构函数,而指向该对象的任何其他普通指针的存在和类型都是无关的。如果指向任何对象的普通指针超出范围,则不会调用任何对象。智能指针可以调用析构函数,在这种情况下,确实需要虚拟分派来确保它是派生类的析构函数
new X
没有作用域。感谢您的更正。实际上我的意思是,当执行“delete bptr”时,只有基类析构函数被调用,除非析构函数是虚拟的。如果派生类对象由基类指针指向,并且当对象超出范围时,只有基类析构函数被调用,除非析构函数是虚拟的。-如果派生类的对象超出范围,则调用派生类析构函数,并且指向该对象的任何其他普通指针的存在和类型都是无关的。如果指向任何对象的普通指针超出范围,则不会调用任何对象。智能指针可以调用析构函数,在这种情况下,确实需要虚拟分派来确保它是派生类的析构函数
new X
没有作用域。感谢您的更正。实际上我的意思是,当执行“delete bptr”时,只有基类析构函数被调用,除非析构函数是虚拟的。