gpt4 book ai didi

c++ - Virtual 关键字使派生对象中的方法不可访问

转载 作者:行者123 更新时间:2023-11-30 00:39:53 24 4
gpt4 key购买 nike

我有这个代码:

#include <iostream>

class Super{
public:
virtual void showName();
};

class Special1 : public Super {
public:
void showName();
void sayHello();
};

class Special2 : public Super {
public:
void showName();
void sayGoodbye();
};

void Super::showName() {
std::cout << "I'm super!" << std::endl;
}

void Special1::showName() {
std::cout << "I'm special1" << std::endl;
}

void Special1::sayHello() {
std::cout << "Hello" << std::endl;
}

void Special2::showName() {
std::cout << "I'm special2" << std::endl;
}

void Special2::sayGoodbye() {
std::cout << "Goodbye" << std::endl;
}

int main () {
Super *oSpec=new Super;

Special1 *o1=static_cast<Special1 *>(oSpec);
Special2 *o2=static_cast<Special2 *>(oSpec);

oSpec->showName();
o1->showName();
o2->showName();

o1->sayHello();
o2->sayGoodbye();

delete oSpec;

return 0;
}

当我运行它时,它显示了这个输出:

I'm super!
I'm super!
I'm super!
Hello
Goodbye

但是,如果我从 Super 类的声明中删除 virtual 关键字:

class Super{
public:
/*virtual*/ void showName();
};

输出变成正确的:

I'm super!
I'm special1
I'm special2
Hello
Goodbye

那么,我的问题是,为什么 virtual 关键字的存在使得指针 o1o2 运行方法 Super::showName() 而不是 Special1::showName()Special2::showName()

最佳答案

输出更接近于 virtual 的正确和不正确的(除非你真的想要那个)。强制转换不会改变对象的类型,只会改变指针的类型。它们仍然是 Super 类型,因此应该运行的是 Super::showName

将一种指针类型转换为另一种指针类型不会改变所指向事物的类型。怎么可能呢?虚函数的全部意义在于能够调用“通用”指针上的方法并获得正确的派生类方法。

为什么要使用虚函数的经典例子是音乐家。您可能有一个函数,通过在它通过的每个 Musician * 上调用 Play 方法来使整个管弦乐队演奏。对于 Pianist,必须调用 Pianist::Play

通常,编译器会在编译时确定调用哪个函数——早期绑定(bind)。编译器肯定知道的唯一信息是指针的类型。当类成员的实际类型已知时,virtual 关键字导致绑定(bind)在运行时延迟发生。

顺便说一句,您仍然可以通过使用范围覆盖来调用基类方法。例如 o1->Super::showName();

事实上,您声称“正确”的结果是灾难性的。使用指向非 Special1 类型(或派生自它的对象)的对象的 this 指针运行 Special1::showName() 是未定义的行为,很容易导致崩溃。

关于c++ - Virtual 关键字使派生对象中的方法不可访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7743775/

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