gpt4 book ai didi

c++ - 将基类指针分配给在自由存储中创建的派生类对象

转载 作者:太空宇宙 更新时间:2023-11-04 11:52:10 25 4
gpt4 key购买 nike

我正在尝试使用 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;}

代码编译正常,但是当我运行它时,出现运行时错误:

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

后跟回溯和内存映射列表

两个 cout 语句都打印在屏幕上,所以我猜错误是在尝试删除 pb2 时产生的。

如果我不指定成员函数 virtual,代码运行正常。如果我在删除 pb1 后重新使用它(即 pb1=new Derived;),而不是创建新指针 pb2,代码也可以正常运行。我在这里缺少什么?

PS:我在 Ubuntu 12.04 中使用 g++ (4.6.4) 和 icc (2013.3.163) 尝试了代码

最佳答案

您正在两个地方进入未定义行为的精彩世界:

delete pb1;
delete pb2;

这是未定义的行为,因为 Base1Base2 都没有 virtual 析构函数,但您正试图删除通过基指针指向的对象。

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

通常,在使用多态性时,您的基类应该始终有一个虚拟析构函数。在许多情况下,这可能是微不足道的:

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

我还要指出,您的层次结构有点……不寻常。一般不需要多重继承。通常有更好的方法来完成您想要做的事情。当您确实使用多重继承时,拥有多个具有同名成员函数的基类几乎总是一个设计缺陷。您通常会遇到意想不到的(但定义明确的)行为。

关于c++ - 将基类指针分配给在自由存储中创建的派生类对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17701250/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com