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

派生类同名成员变量未覆盖基类?C++代码行为疑问

为什么派生类同名成员不会让基类函数调用到派生类的成员?

你的代码运行后打印from foo而非from override foo,核心原因是派生类的m_data并没有覆盖基类的m_data,而是定义了一个同名的独立成员,属于C++的「名字隐藏」规则,具体拆解如下:

1. 内存中的两个独立成员

基类Base和派生类Derived的m_data是完全分开的两个成员,在对象内存布局中同时存在:

  • 基类Base自带一个Foo* m_data,初始化指向Foo对象;
  • 派生类Derived额外定义了一个t* m_data(这里t是OverrideFoo),初始化指向OverrideFoo对象。

2. 成员函数的作用域规则

基类的useData()函数属于Base类的作用域,它里面的m_data只会绑定到Base类自己的成员,和派生类的同名成员毫无关系。哪怕你通过派生类对象调用useData(),函数的执行逻辑仍然遵循基类的作用域,只会访问基类的Foo* m_data,所以打印from foo。

反过来,如果在派生类中定义自己的成员函数:

template <class t> 
struct Derived : public Base {
    t* m_data {new t()};
    void printDerived() {
        m_data->print(); // 这里访问的是派生类的m_data,会打印"from override foo"
    }
};

调用d.printDerived()就会得到你预期的结果,因为这个函数属于派生类作用域,优先访问派生类的同名成员。

3. 非模板场景的验证

这种行为和模板无关,普通派生类也会出现相同情况:

struct Derived : public Base {
    OverrideFoo* m_data {new OverrideFoo()};
};

此时调用Derived对象的useData(),依然会打印from foo,原因和上面完全一致。

如何让基类函数使用派生类成员?

如果想让基类的useData()能调用到派生类的成员,需要用多态或者**模板继承(CRTP)**的方式:

  • 多态方案:让Foo和OverrideFoo继承自同一个基类,把print()定义为虚函数,基类Base的m_data改为基类指针;
  • CRTP方案:让基类依赖派生类类型,直接访问派生类的成员。

比如多态的实现示例:

struct BaseFoo {
    virtual void print() = 0;
    virtual ~BaseFoo() = default;
};

struct Foo : BaseFoo {
    void print() override {
        printf("from foo\n");
    }
};

struct OverrideFoo : BaseFoo {
    void print() override {
        printf("from override foo\n");   
    }
};

struct Base {
    virtual BaseFoo* getData() {
        return m_data;
    }
    void useData() {
        getData()->print();
    }
    Foo* m_data {new Foo()};  
};

template <class t> 
struct Derived : public Base {
    t* m_data {new t()};
    BaseFoo* getData() override {
        return m_data;
    }
};

这时调用d.useData()就会打印from override foo。

内容的提问来源于stack exchange,提问作者pepero

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 08:01:55