覆盖派生类中的成员字段

Sum*_*Tea 10 c++ c++11

我有一个代码片段如下:

#include <iostream>

using namespace std;

class Base {
public:
    Base() : b(0) {}
    int get();
    virtual void sayhello() { cout << "Hello from Base with b: " << b << endl; }
private:
    int b;
};

int Base::get() {sayhello(); return b;} 

class Derived : public Base {
public:
    Derived(double b_):b(b_){}
    void sayhello() { cout << "Hello from Derived with b: " << b << endl; }
private:
    double b;
};

int main() {
    Derived d(10.0);
    Base b = d;

    cout << "Derived b: " << d.get() << endl;
    cout << "Base b: " << b.get() << endl;
}
Run Code Online (Sandbox Code Playgroud)

运行已编译的可执行文件,我发现结果超出了我对llvm-g ++ 4.2机器的期望.我的盒子上的输出是

Hello from Derived with b: 10
Derived b: 0
Hello from Base with b: 0
Base b: 0
Run Code Online (Sandbox Code Playgroud)

我想在代码中做的是覆盖类中的成员字段(b)Derived.因为我认为无论是BaseDerived需要访问这个领域,我定义了一个get在成员函数Base,因此Derived可以继承它.然后我尝试从不同的对象获取成员字段.

结果表明,我仍然得到原bBase通过d.get()的而不是在Derived,这就是我所期待的代码来执行.代码(或我的理解)有什么问题吗?是否在规范中指定了此行为?覆盖成员字段并正确定义其getter和setter的正确方法是什么?

mas*_*oud 14

b派生类中添加的新内容不会覆盖base b.它只是隐藏它.

因此,在派生类中,您有两个b并且虚拟方法打印对应b.

  • 因为`get()`不是虚拟的,它返回在`Base`类中定义的`b`.它对`Derived`类一无所知,所以它显然不能返回`Derived :: b`成员的值.只有`sayhello()`是虚拟的,因此它是唯一可以从`Derived`返回`b`的方法. (7认同)
  • @StephaneRolland所以正确的方法是?你能把这个想法变成一个答案吗?谢谢 :). (3认同)
  • 您只覆盖函数,而不覆盖数据成员。 (3认同)
  • 首先,你不应该这样隐藏变量. (2认同)

Geo*_*roy 7

您不能简单地覆盖成员字段,并且在Base::get编译时,b变量将被解析为,Base::b因此此方法将始终使用此值,而不是来自派生类中具有相同名称的另一个字段的值.

覆盖属性的常用方法是覆盖访问它的方式,即覆盖访问器(getter和setter).

你可以通过装饰getter来实现类似的东西,但getter返回类型将始终是相同的:

class Base {
public:
    Base() : b(0) {}
    int get();
    virtual void sayhello() { cout << "Hello from Base with b: " << b << endl; }
protected:
    virtual int getB() {return b;}
private:
    int b;
};

int Base::get() {sayhello(); return getB();} 

class Derived : public Base {
public:
    Derived(double b_):b(b_){}
    void sayhello() { cout << "Hello from Derived with b: " << b << endl; }
protected:
    int getB() override {return b;} // conversion from double to int
private:
    double b;
};
Run Code Online (Sandbox Code Playgroud)