You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 07:03:31