gpt4 book ai didi

C++ 继承 : Derived class pointer to a Base class invokes Derived class method

转载 作者:行者123 更新时间:2023-11-30 01:11:29 28 4
gpt4 key购买 nike

我正在学习 C++ 继承,所以我通过动态创建一个 Base 类来尝试这段代码,并对它的 Derived 类进行向下转换(显然向下转换无效)以使这个动态创建的 Base 对象被指向派生类指针。但是当我通过这个 Derived 指针调用方法 who() 时,它会调用 Derived 类方法而不是 Base 类方法。

根据我的假设,没有为派生类创建对象,那么怎么可能调用未创建的派生类对象的方法而不是实际创建的基类对象呢?

我用谷歌搜索了这种现象,但找不到关于调用未创建的派生类对象的方法的清晰明了的解释。如果它符合标准,请向我解释它是如何工作的。我知道如果我将方法设为 virtual,情况会有所不同,但此处使用的方法不是 virtual

class parent{
public:
void who(){
cout << "I am parent";
}
};

class child : public parent{
public:
void who(){
cout << "I am child";
}
};

int main(){
child *c = (child *)new parent();
c->who();
return 0;
}

输出是 I am child 但我期望 I am parent

编辑:我没有在上面的代码中释放内存并进行无效的向下转换,因为我只是想看看会发生什么。所以只解释这种只调用方法的行为。

最佳答案

您的代码以这种方式运行的原因可能是因为编译器不检查您的对象的实际类型(除非您的函数是 virtual,否则不需要检查);它只是调用 child::who 因为你告诉它这样做。也就是说,您的代码肯定是可疑的。

你是静态downcasting基类指针指向派生类指针,不是type-safe . C++ 不会阻止你这样做;确保您的指针确实指向派生类型的对象取决于您。如果指针不引用派生类型的对象,则取消引用指针可能是 undefined behaviour .您很幸运,您的代码甚至可以打印任何内容。

需要确保您的基类函数whovirtual,否则函数调用将不会运行polymorphically .请记住,一旦您将 virtual 添加到您的 代码中,您肯定会调用未定义的行为,因为您正在非法向下转换为无效类型。您可以使用 dynamic_cast 安全地向下转型, 如果对象不是指定类型,它将返回一个 nullptr

您的基类中通常还应该有一个虚拟 析构函数,这样您的对象就可以删除多态。说到这一点,您还需要确保在某个时候删除您的动态分配对象。通过手动调用newdelete,很容易像这样泄漏内存,即使您知道需要调用deletestd::unique_ptrstd::shared_ptr被添加到 C++11 的标准库中以解决这些问题。在除最低级代码之外的所有代码中使用这些而不是 newdelete

总而言之,我建议您的代码应该如下所示:

#include <iostream>
#include <memory>

class parent {
public:
virtual ~parent() {}

virtual void who() {
std::cout << "I am parent";
}
};

class child : public parent {
public:
void who() override {
std::cout << "I am child";
}
};

int main() {
auto p = std::make_unique<parent>();
auto c = dynamic_cast<child*>(p.get());

if (c) // will obviously test false in this case
{
c->who();
}
}

关于C++ 继承 : Derived class pointer to a Base class invokes Derived class method,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36063911/

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