众所周知,我们可以使用指向基类的指针来访问派生类中基类的重写虚函数。
下面是一个这样的例子。
#include <iostream>
class shape {
public:
virtual void draw() {
std::cout << "calling shape::draw()\n";
}
};
class square : public shape {
public:
virtual void draw() {
std::cout << "calling square::draw()\n";
}
int area() {
return width*width;
}
square(int w) {
width = w;
}
square() {
width = 0;
}
protected:
int width;
};
class rect : public square {
public:
virtual void draw() {
std::cout << "calling rect::draw()\n";
}
int area() {
return width*height;
}
rect(int h, int w) {
height = h;
width = w;
}
protected:
int height;
};
int main() {
/*
shape* pshape[3] = {
new shape,
new square(2),
new rect(2, 3)
};
for (int i = 0; i<3; i++){
pshape[i]->draw();
}
*/
square* psquare = new rect(2, 3);
psquare->draw();
system("pause");
return 0;
}
pshape[i]
指针可以轻松访问虚函数draw()
。
现在是令人困惑的部分。 “方形”类是“矩形”类的基类。因此,如果有一个 square* 指针,它可以访问“rect”类(square* psquare = new rect(2, 3);) 的 draw()
函数,并且输出是:
calling rect::draw()
Press any key to continue . . .
现在,如果我从 square::draw() 定义中删除“virtual”关键字,它的代码仍然可以编译并且输出是相同的:
calling rect::draw()
Press any key to continue . . .
最后,如果我从基本函数中删除“virtual”,psquare->draw()
的输出是:
calling square::draw()
Press any key to continue . . .
这让我很困惑。这里到底发生了什么?
- 因为
square
是rect
类的父类,square
应该有它的draw()
函数是虚函数为了让rect
覆盖它。但它仍在编译并提供与虚拟化时相同的输出。 - 因为
shape
是所有类的基类,去掉shape中draw()的virtual
关键字应该会出错。但这并没有发生,它正在编译并在调用psquare->draw()
时给出另一个输出calling square::draw()
。
我可能在很多事情上都是错的。请更正错误并告诉我这里到底发生了什么。
最佳答案
如果一个函数在基类中声明为虚函数,那么它在所有派生类中自动为虚函数,就像您在其中放置一个virtual
关键字一样。参见 C++ "virtual" keyword for functions in derived classes. Is it necessary? .
如果函数不是虚函数,那么调用哪个版本将取决于调用它的指针类型。调用父类中的成员函数绝对没问题,因为派生类的每个实例都是其每个父类的实例。所以那里没有错误。
关于c++ - 虚函数指针混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42605614/