为何C++中Lion子类未按预期调用Leg类函数?结果不符预期
问题分析:为何代码未输出预期的"This is a Leg"?
问题描述
我预期以下代码输出"This is a Leg",因为我的Lion类中包含一个私有Leg类型成员变量,但实际运行结果并非如此,请帮忙分析原因。
代码示例
#include <iostream> using namespace std; class Limb{ public: std::string getFullName() const{ auto name = getName(); return "This is a " + name; } private: virtual std::string getName() const{ return "Limb!"; } }; class Leg: public Limb { private: std::string getName() const override{ return "Leg!"; //This is overriding the parent class's getName } }; class Animal{ public: Animal():x_(){} Limb getLimb() const{ return x_; // This should return a Leg instance when running under `Lion`, right? } std::string getLimbName() const{ return getLimb().getFullName(); } private: Limb x_; }; class Lion: public Animal{ public: Lion():x_(){} private: Leg x_; //I explicitly want a Leg instance, not an Animal. }; int main() { Lion l = Lion(); std::cout<<l.getLimbName()<<std::endl; return 0; }
原因分析
两个
x_是完全独立的成员变量:Lion继承Animal后,自己又定义了一个Leg x_,这和Animal类里的Limb x_没有任何关联。Animal的成员函数getLimb()只会访问自己类内声明的x_,根本不会去调用Lion里的那个Leg x_。值返回触发对象切片:就算Animal里的
x_是Leg类型,getLimb()返回的是Limb类型对象,这会发生对象切片——Leg对象中属于子类独有的部分会被截断,只剩下基类Limb的内容,调用虚函数时自然会执行基类的getName()实现。继承逻辑错误:你想让父类Animal的成员函数使用子类Lion的成员变量,这违背了继承的设计逻辑。父类无法直接访问子类新增的成员,Animal类根本不知道Lion有自己的
x_变量。
修正思路
要实现多态效果,需要让Animal持有Limb的指针或引用,子类Lion负责初始化这个指针为Leg实例:
#include <iostream> using namespace std; class Limb{ public: virtual ~Limb() = default; // 必须加虚析构,避免内存泄漏 std::string getFullName() const{ auto name = getName(); return "This is a " + name; } private: virtual std::string getName() const{ return "Limb!"; } }; class Leg: public Limb { private: std::string getName() const override{ return "Leg!"; } }; class Animal{ public: Animal():x_(new Limb()){} virtual ~Animal() { delete x_; } // 虚析构确保子类对象能正确销毁 const Limb& getLimb() const{ return *x_; } std::string getLimbName() const{ return getLimb().getFullName(); } protected: Limb* x_; // 改为protected,让子类可以修改 }; class Lion: public Animal{ public: Lion():Animal(){ delete x_; // 删除基类创建的Limb x_ = new Leg(); // 替换为Leg实例 } }; int main() { Lion l; std::cout<<l.getLimbName()<<std::endl; return 0; }
内容的提问来源于stack exchange,提问作者user1008636
相关产品推荐
相关产品推荐

