gpt4 book ai didi

c++ - 在 C++ 中隐藏、重载或覆盖

转载 作者:太空狗 更新时间:2023-10-29 19:52:27 25 4
gpt4 key购买 nike

那我再问一个问题。像这样:

#include <iostream>
using namespace std;

class Base
{
public:
void foo()
{
cout<<"Base."<<endl;
}
};

class Derive:public Base
{
public:
void foo()
{
cout<<"Derive."<<endl;
}
};

int main()
{
Derive d;
Base *pb=&d; //attention here
pb->foo(); //ateention here
system("pause");
return 0;
}

输出是“Base.”。然后功能规则不起作用,我对此感到困惑,你能帮帮我吗?谢谢。

最佳答案

由于 foo 不是虚拟的,调用的函数基于 static 类型(即声明指针指向的类型)而不是动态类型(指针当前指向的对象类型)。

还有一些更棘手的情况需要考虑。有一点(其他一些答案实际上有些误导)是,重要的不仅仅是函数 name ,而是整个函数签名。例如:

#include <iostream>

struct base {
virtual void foo() {
std::cout << "base::foo";
}
};

struct derived : base {
virtual void foo() const {
std::cout << "derived::foo";
}
};

int main(){
base *b = new derived;

b->foo();
}

这里 foo 在基类和(看似多余的)派生类中都被限定为 virtual,但是调用 b->foo() 仍然 打印出 base::foo

添加到 derived::foo 签名的 const 意味着它不再匹配 base::foo 的签名,所以改为重写虚函数后,我们仍然得到两个同名的独立函数,所以 derived::foo 隐藏了 base::foo,但没有重写它.尽管 virtual 资格,我们得到静态绑定(bind),所以 b->foo(); 调用基函数而不是派生函数,即使 b 指向 derived 类型的对象。

正如 Tony D 在评论中指出的那样,C++11 为该语言添加了一个新功能以帮助防止这种情况发生。当你想覆盖一个基类函数时,你可以在派生类中的函数中添加标识符override:

struct derived : base {
virtual void foo() const override {
std::cout << "derived::foo";
}
};

这样,如果函数签名存在差异(如此处所示的情况),编译器将生成一条错误消息,提醒您 derived::foo 被标记为 override,但实际上并没有覆盖基类中的函数。然而,这是在 C++11 中添加的,因此如果您使用的是较旧的编译器,则可能无法实现此功能(不过值得庆幸的是,未实现它的编译器很快就会被遗忘)。

将基类中的签名更正为:

virtual void foo() const // ...

...将使代码编译并产生正确的结果。

关于c++ - 在 C++ 中隐藏、重载或覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25517709/

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