C++继承问题:基类指针能否访问派生类成员变量?
基类智能指针访问派生类成员的差异解析
问题描述
给定基类
Shape与派生类Rectangle,尝试通过基类的std::shared_ptr访问Rectangle的成员变量width,代码如下:
class Shape { public: Shape() {}; }; class Rectangle : public Shape // 注:原代码遗漏继承关系,此处补充以符合逻辑 { public: Rectangle(int width) : width(width) {} // 修正原构造函数的赋值逻辑为初始化列表 int width; }; // 运行时执行代码 std::shared_ptr<Shape> ptr = std::make_shared<Rectangle>(10); ptr->width; // 此操作会报错?
实际代码中ptr->width会报错,但如果compute_area()是Rectangle重写的成员函数,调用ptr->compute_area()却不会报错,请问这是为什么?
原因解析
1. 访问成员变量width报错的原因
- C++是静态类型语言,编译阶段会严格检查指针的声明类型。
std::shared_ptr<Shape>类型的ptr,编译器仅认为它指向Shape类对象,而Shape类中并没有width成员,因此编译直接报错,不会进入运行阶段。 - 即便运行时
ptr实际指向的是Rectangle对象,静态类型检查不会考虑运行时的实际对象类型,只依据指针的声明类型做校验。
2. 重写的虚函数可以正常调用的原因
- 这依赖于C++的多态机制:如果基类
Shape中把compute_area()声明为虚函数(比如virtual double compute_area() = 0;),那么所有派生类的对象会携带一个指向虚函数表(vtable)的指针。 - 当通过基类指针调用虚函数时,程序会在运行时根据实际指向的对象类型(这里是
Rectangle),找到对应类的虚函数表,进而调用Rectangle中重写的compute_area()版本。 - 注意:如果基类没有将
compute_area()声明为虚函数,直接调用ptr->compute_area()要么会调用基类的版本(若基类有该函数),要么同样会编译报错(若基类无此函数)。
内容的提问来源于stack exchange,提问作者SolidMechanicsFan
相关产品推荐
相关产品推荐

