C++ 覆盖派生类中的成员字段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19290796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:40:43  来源:igfitidea点击:

Override member field in derived classes

c++c++11

提问by Summer_More_More_Tea

I have a code snippet below:

我在下面有一个代码片段:

#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 the compiled executable and I find the result is out of my expectation on my llvm-g++ 4.2machine. The output on my box is as

运行编译后的可执行文件,我发现结果在我的llvm-g++ 4.2机器上超出了我的预期。我的盒子上的输出是

Hello from Derived with b: 10
Derived b: 0
Hello from Base with b: 0
Base b: 0

What I want to do in the code is to override a member field (b) in Derivedclass. Since I think both Baseand Derivedneed to access this field, I define a getmember function in Base, thus Derivedcan inherit it. Then I try to get the member field from different objects.

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

The result shows that I still get original bin Baseby d.get()instead of that in Derived, which is what I expected the code to do. Anything wrong with the code (or my understanding)? Is this behavior specified in the specification? What is the right way to override a member field and properly define its getter and setter?

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

回答by masoud

The new badded in the derived class doesn't override base's b. It just hidesit.

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

So, in the derived class you have two band the virtual method prints corresponding b.

因此,在派生类中有两个b,虚拟方法打印相应的b.

回答by Geoffroy

You can't simply override a member field, and as Base::getis compiled, the bvariable is resolved to Base::bso this method will always use this value and not a value from another field with the same name in a derived class.

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

The usual way to override an attribute is to override the way you access it, i.e. override the accessors (getter and setter).

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

You can achieve something like that by decorating the getter, but the getter return type will always be the same:

您可以通过装饰 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;
};

回答by Daniel Frey

I'm not sure I understand you correctly, but it by "override" you mean "replace", you'd use a template:

我不确定我是否正确理解您,但是“覆盖”的意思是“替换”,您将使用模板:

#include <iostream>
using namespace std;

template< typename T >
class Base {
public:
    Base() : b(0) {}
    Base(T b_) : b(b_) {}
    T get();
    virtual void sayhello() { cout << "Hello from Base with b: " << b << endl; }
protected:
    T b;
};

template< typename T >
T Base<T>::get() {sayhello(); return b;} 

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

int main() {
    Derived d(10.0);
    Base<double>* b = &d;

    cout << "Derived b: " << d.get() << endl;
    cout << "Base b: " << b->get() << endl;
}

You code in mainwas also attempting Base b = d;which would lead to slicing, the above fixes that and makes sure you don't accidentially use Base<int>instead of Base<double>.

您输入的代码main也在尝试Base b = d;这会导致切片,上述修复了该问题并确保您不会意外地使用Base<int>代替Base<double>.

Live example

活生生的例子

回答by zabulus

you should rewrite your Derived::ctor as follows:

你应该重写你的 Derived::ctor 如下:

Derived(double _b)
:Base(_b)
{}

And remove filed bin Derived class. Instead mark bin the Baseclass as protected.

并删除b派生类中的归档。而是bBase类中标记为受保护。

EDIT
Disregard all of this I've found a problem in your code:

编辑
忽略所有这些我在你的代码中发现了一个问题:

Base b = d;

You're copyingderived object to base. It copies only base fields. If you want polymorphism try next:

您正在派生对象复制到基础。它只复制基本字段。如果您想要多态性,请尝试下一步:

Base *b = &d;
b->get()