将基类指针指定给在空闲存储中创建的派生类对象 我正在试用C++,试图理解继承并编写了以下代码: #include <iostream> #include <cstdlib> class Base1{ public: virtual void print_hello() const { std::cout << "Base1: Hello!" << std::endl;} }; class Base2{ public: virtual void print_hello() const { std::cout << "Base2: Hello!" << std::endl; } }; class Derived: public Base1, public Base2 { public: virtual void print_hello() const { std::cout << "Derived: Hello!" << std::endl; } }; int main() { Base1* pb1=new Derived; pb1->print_hello(); delete pb1; Base2* pb2=new Derived; pb2->print_hello(); delete pb2; return EXIT_SUCCESS;}

将基类指针指定给在空闲存储中创建的派生类对象 我正在试用C++,试图理解继承并编写了以下代码: #include <iostream> #include <cstdlib> class Base1{ public: virtual void print_hello() const { std::cout << "Base1: Hello!" << std::endl;} }; class Base2{ public: virtual void print_hello() const { std::cout << "Base2: Hello!" << std::endl; } }; class Derived: public Base1, public Base2 { public: virtual void print_hello() const { std::cout << "Derived: Hello!" << std::endl; } }; int main() { Base1* pb1=new Derived; pb1->print_hello(); delete pb1; Base2* pb2=new Derived; pb2->print_hello(); delete pb2; return EXIT_SUCCESS;},c++,virtual,new-operator,C++,Virtual,New Operator,后面是回溯跟踪和内存映射列表 两个cout语句都打印在屏幕上,所以我猜错误源于尝试删除pb2时 如果我没有指定成员函数,代码运行正常。如果在删除pb1后重新使用它(即pb1=new-Derived;),而不是创建新指针pb2,那么代码也可以正常运行。我错过了什么 PS:我用g++(4.6.4)和icc(2013.3.163)在Ubuntu12.04中尝试了这段代码。当您通过指向基类型的指针删除派生类型的对象时,基类型必须有一个虚拟析构函数。没有它,你就有了未定义的行为。因此:将虚拟析构函数添加到

后面是回溯跟踪和内存映射列表

两个cout语句都打印在屏幕上,所以我猜错误源于尝试删除pb2时

如果我没有指定成员函数,代码运行正常。如果在删除pb1后重新使用它(即
pb1=new-Derived;
),而不是创建新指针pb2,那么代码也可以正常运行。我错过了什么


PS:我用g++(4.6.4)和icc(2013.3.163)在Ubuntu12.04中尝试了这段代码。

当您通过指向基类型的指针删除派生类型的对象时,基类型必须有一个虚拟析构函数。没有它,你就有了未定义的行为。因此:将虚拟析构函数添加到
Base1
Base2
当您通过指向基类型的指针删除派生类型的对象时,基类型必须具有虚拟析构函数。没有它,你就有了未定义的行为。因此:在
Base1
Base2
中添加一个虚拟析构函数,您将在两个地方进入一个奇妙的未定义行为世界:

delete pb1;
delete pb2;
这是未定义的行为,因为niether
Base1
Base2
具有
virtual
析构函数,但您正试图
删除通过基指针指向的对象

第一个实例(
delete pb1
)也是未定义的行为,这可能会让您感到惊讶,因为它似乎可以工作。这就是未定义行为的美妙之处——任何事情都可能发生,甚至是你期望发生的事情

通常,在使用多态性时,基类应该始终具有
virtual
析构函数。在许多情况下,它可能是微不足道的:

class Base1{
public:
    virtual void print_hello() const
    { std::cout << "Base1: Hello!" << std::endl;}
      virtual ~Base1() {}
};

class Base2{
public:
    virtual void print_hello() const
    { std::cout << "Base2: Hello!" << std::endl; }
      virtual ~Base2() {};
};
classbase1{
公众:
虚拟空打印\u hello()常量

{std::cout你正在两个地方进入一个奇妙的未定义行为的世界:

delete pb1;
delete pb2;
这是未定义的行为,因为niether
Base1
Base2
具有
virtual
析构函数,但您正试图
删除通过基指针指向的对象

第一个实例(
delete pb1
)也是未定义的行为,这可能会让您感到惊讶,因为它似乎是有效的。这就是未定义行为的美妙之处——任何事情都可能发生,甚至是您期望发生的事情

通常,在使用多态性时,基类应该始终具有一个
virtual
析构函数。在许多情况下,它可能很简单:

class Base1{
public:
    virtual void print_hello() const
    { std::cout << "Base1: Hello!" << std::endl;}
      virtual ~Base1() {}
};

class Base2{
public:
    virtual void print_hello() const
    { std::cout << "Base2: Hello!" << std::endl; }
      virtual ~Base2() {};
};
classbase1{
公众:
虚拟空打印\u hello()常量

{std::cout也许您可以在所有类上添加一个析构函数,其中包含一些cout语句,以查看删除指针时发生的情况。也许您可以在所有类上添加一个析构函数,其中包含一些cout语句,以查看删除指针时发生的情况。