C++多态疑问:调用printArea(r)时为何不受shape指针指向影响?
老哥,首先得帮你理清一个关键误解:你提到的那个Shape类型指针shape,它当前指向c(Circle对象)这件事,和你调用printArea(r)完全是八竿子打不着的两个独立操作,互相没有任何影响!
先补全你没写完的代码(合理推测)
你贴的代码里Circle的getArea没写完,而且缺了printArea函数的定义,我先补全成能正常运行的版本,方便后续解释:
#include<iostream> using namespace std; class Shape { public: virtual float getArea() const = 0; // 纯虚函数,Shape是抽象类 }; class Rectangle : public Shape { private: float width; float height; public: Rectangle(float width, float height) : width(width), height(height) {} float getArea() const {return width * height;} // 重写基类虚函数 }; class Circle : public Shape { private: float radius; public: Circle(float radius) : radius(radius) {} float getArea() const { // 补全你没写完的部分 return 3.14159 * radius * radius; } }; // 推测的printArea函数定义(这是能正确触发多态的写法) void printArea(const Shape& shape) { cout << "面积是:" << shape.getArea() << endl; } int main() { Rectangle r(2, 3); Circle c(5); Shape* shape = &c; // 这个指针指向c,但和printArea调用半毛钱关系都没有 printArea(r); // 调用这个时,完全用的是r本身,和上面的shape指针无关 printArea(c); return 0; }
为什么printArea(r)能正确执行?
核心原因有两个:
参数传递和那个全局指针无关:
你调用printArea(r)时,是直接把r这个Rectangle对象作为参数传给函数,那个Shape* shape指针是另一个独立的变量,它指向谁根本不会影响printArea的参数传递——就像你口袋里揣着一把钥匙指向家门,不影响你手里拿着另一把钥匙开办公室门一样。基类引用触发多态:
上面的printArea函数参数是const Shape& shape(基类引用),当你把Rectangle对象r绑定到这个引用上时,C++会保留对象的实际类型信息。因为getArea是虚函数,编译器会通过虚表(vtable)机制,自动找到实际对象(也就是Rectangle)的getArea重写版本,所以计算的就是矩形的面积,自然正确。
额外唠一句:如果printArea是传值会怎样?
要是你把printArea写成传值(void printArea(Shape shape)),那反而会编译报错——因为Shape是包含纯虚函数的抽象类,不能被实例化,传值的时候会发生对象切片,试图把Rectangle切成Shape对象,这是C++不允许的。所以正确的多态调用必须用基类引用或者基类指针作为参数。
内容的提问来源于stack exchange,提问作者netleap tom

