c++ - C++ 中的覆盖函数不起作用

标签 c++ function inheritance polymorphism overriding

#include <cstdio>
using namespace std;

class A {
public:
    virtual void func() { printf("A::func()"); }
};

class B : public A {
public:
    virtual void func() { printf("B::func()"); }
};

int main() {
  A a = *(A *)new B();
  a.func();
}

问题很简单:为什么 a->func() 调用类 A 中的函数,即使 a 包含类 B 的对象?

最佳答案

A a = *(A *)new B();
a.func();

这是这段代码中发生的事情,一步一步:

  • new B():一个新的 B 类型对象被分配到空闲存储区,产生它的地址
  • (A*):对象的地址被转换为A*,所以我们实际上有一个A*类型的指针指向有效的 B 类型对象。一切顺利。
  • A a:问题从这里开始。 A 类型的新本地对象 在堆栈上创建并使用复制构造函数A::A(const A&) 构造,第一个参数是之前创建的对象.
  • 指向 B 类型原始对象的指针在此语句后丢失,导致内存泄漏,因为它是使用 new 在空闲存储上分配的。
  • a.func() - 该方法在类 A 的(本地)对象上调用。

如果将代码更改为:

A& a = *( A*) new B();
a.func();

然后只会构造一个对象,它的指针将被转换为A* 类型的指针,然后取消引用并使用该地址初始化一个新的引用。虚函数的调用将动态解析为 B::func()


但请记住,您仍然需要释放该对象,因为它是用 new 分配的:

delete &a;

顺便说一句,只有当 A 有一个虚拟析构函数时才是正确的,这是 B::~B() 所必需的(幸运的是这里是空的,但在一般情况下不需要)也会被调用。如果 A 没有虚拟析构函数,那么您需要通过以下方式释放它:

delete (B*)&a;

如果您想使用指针,那么这与引用相同。代码:

A* a = new B(); // actually you don't need an explicit cast here.
a->func();
delete (B*)a; // or just delete a; if A has a virtual destructor.

关于c++ - C++ 中的覆盖函数不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4574321/

相关文章:

Javascript/ExtJS : Ext. getCmp ('' ) 导致 TypeError ...不是一个函数

django - 重命名 Django 父类(super class)模型并正确更新子类指针

c# - 抽象类和接口(interface)中可以使用相同的字段名称吗?

c++ - 控制 USB 端口

c++ - 在 eclipse makefile 项目中设置主要功能

c++ - 在 C++ 中使用带有映射的插入的效率

javascript - 如何从网站调用 Javascript 函数?

function - 如何检查 R 中对象类敏感函数的代码

java - 子类无法被保护

c++ - 与 std::lock_guard 相比,std::scoped_lock 的目的是否仅用于处理多个互斥量?