简体   繁体   English

将基类指针分配给免费商店中创建的派生类对象

[英]assigning a base class pointer to a derived class object created in the free store

I was experimenting with c++, trying to understand inheritance and wrote the following code: 我正在尝试使用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;}

The code compiled ok but when I ran it, I got a run time error: 代码编译正常,但是当我运行它时,出现运行时错误:

Derived: Hello!
Derived: Hello!
*** glibc detected *** ./a.out: free(): invalid pointer: 0x0000000001b0c018 ***

followed by a Back trace and a memory map list 然后是返回跟踪和内存映射列表

Both cout statements were printed in the screen so I guess the error originates when trying to delete pb2. 屏幕上都打印了两个cout语句,所以我猜想错误是由于尝试删除pb2而引起的。

If I do not specify the member functions virtual, the code runs ok. 如果我未将成员函数指定为虚拟,则代码运行正常。 The code also runs ok if I reuse pb1 after I delete it (ie pb1=new Derived; ), instead of creating the new pointer pb2. 如果我在删除pb1之后重用了pb1(即pb1=new Derived; ),而不是创建新的指针pb2,则代码也可以正常运行。 What am I missing here? 我在这里想念什么?

PS: I tried the code in Ubuntu 12.04 using both g++ (4.6.4) and icc (2013.3.163) PS:我在Ubuntu 12.04中使用g ++(4.6.4)和icc(2013.3.163)尝试了代码

You are entering in to the wonderful world of Undefined Behavior, in two places: 您将在两个地方进入“未定义行为”的奇妙世界:

delete pb1;
delete pb2;

This is Undefined Behavior because niether Base1 nor Base2 have virtual destructors, but you are trying to delete the objects pointed to through a base pointer. 这是未定义行为,因为niether Base1 ,也不Base2virtual析构函数,但你想delete的对象指出,通过基类指针。

It might suprise you that the first instance ( delete pb1 ) is also Undefined Behavior, because it appears to work. 您可能会感到惊讶,第一个实例( delete pb1 )也是未定义行为,因为它似乎可以工作。 That's the beauty of Undefined Behavior -- anything can happen, even what you were expecting to happen. 这就是未定义行为的美丽-可能发生任何事情,甚至是您期望发生的事情。

As a rule, when using polymorphism your base classes should always have a virtual destructor. 通常,使用多态时,您的基类应始终具有virtual析构函数。 In many cases, it can be trivial: 在许多情况下,这可能是微不足道的:

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() {};
};

I'll also point out that your hierarchy is somewhat... unusual . 我还要指出,您的层次结构有些... 不寻常 Generally multiple inheritence is not needed. 通常不需要多重继承。 There are usually better ways to accomplish what you're trying to do. 通常,有更好的方法可以完成您想做的事情。 When you do use multiple inheritence, it's almost always a design flaw to have multiple base classes that have member functions with the same name. 当您使用多重继承时,拥有多个具有相同名称的成员函数的基类几乎总是一个设计缺陷。 You are generally going to get unexpected (but well-defined) behavior. 通常,您将获得意外(但定义明确)的行为。

When you delete an object of a derived type through a pointer to the base type, the base type must have a virtual destructor. 当通过指向基本类型的指针删除派生类型的对象时,该基本类型必须具有虚拟析构函数。 Without it you have undefined behavior. 没有它,您将无法定义行为。 So: add a virtual destructor to Base1 and to Base2 . 因此:将虚拟析构函数添加到Base1Base2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM