下列代码中, s1->draw(); 和 s2->draw(); 输出不同结果的主要原因是( )。
class Shape {
public:
virtual void draw() {
cout << "绘制图形" << endl;
}
virtual ~Shape() {}
};
class Circle : public Shape {
public:
void draw() override {
cout << "绘制圆形" << endl;
}
};
class Rectangle : public Shape {
public:
void draw() override {
cout << "绘制矩形" << endl;
}
};
int main() {
Shape* s1 = new Circle();
Shape* s2 = new Rectangle();
s1->draw();
s2->draw();
delete s1;
delete s2;
return 0;
}C++类:构造函数(对象创建时调用)、析构函数(对象销毁时调用)、虚函数(实现多态)。构造函数不能为虚。
构造函数不能是虚函数(虚表在构造函数完成后才建立)。析构函数可以且通常应该为虚函数(防止内存泄漏)。
【考点】虚函数机制|动态联编|多态继承
看到题先定位基类Shape的draw()是否加了virtual——答案在代码第一行就写死了。然后对比选项:A说"是普通成员函数",但代码明明写了virtual;C说"public继承",虽然对,但不是差异原因;D说"指针变量名不同",这跟函数行为无关。只有B"Shape中的draw()被声明为虚函数"直接解释了为什么调用时能区分对象实际类型。
陷阱在于"继承≠多态"。很多学生选了C,以为只要继承就能多态,却忘了基类必须声明virtual。题目里Shape的draw()明明写了virtual,如果它没写,那s1->draw()就会直接调用基类版本,输出"绘制图形",和s2->draw()一样。A选项是偷换概念,把虚函数说成普通函数;D选项是抓不住语义,指针名不同不影响调用逻辑。最阴险的是C——它看似正确,却忽略了"虚表"的存在,只背了"继承"没背"虚函数"。
如果把Shape中的virtual去掉,s1->draw()和s2->draw()都会调用基类版本,答案就变成A了。如果把Circle和Rectangle的draw()改成static,那也不会有多态,答案会变成C。如果把s1改成Circle*、s2改成Rectangle*,那直接静态绑定,答案会变D。刷到类似题先问:这题考的是"虚函数"还是"继承"还是"指针类型"?