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
Override member field in derived classes
提问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 Derived
class.
Since I think both Base
and Derived
need to access this field, I define a get
member function in Base
, thus Derived
can inherit it.
Then I try to get the member field from different objects.
我想在代码中做的是覆盖类中的成员字段 ( b
) Derived
。因为我认为无论是Base
和Derived
需要访问这个领域,我定义了一个get
在成员函数Base
,因此Derived
可以继承它。然后我尝试从不同的对象中获取成员字段。
The result shows that I still get original b
in Base
by 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?
结果表明,我仍然得到原b
在Base
通过d.get()
的而不是在Derived
,这就是我所期待的代码来执行。代码(或我的理解)有什么问题吗?规范中是否指定了此行为?覆盖成员字段并正确定义其 getter 和 setter 的正确方法是什么?
回答by masoud
The new b
added in the derived class doesn't override base's b
. It just hidesit.
b
派生类中添加的新内容不会覆盖基类的b
. 它只是隐藏它。
So, in the derived class you have two b
and the virtual method prints corresponding b
.
因此,在派生类中有两个b
,虚拟方法打印相应的b
.
回答by Geoffroy
You can't simply override a member field, and as Base::get
is compiled, the b
variable is resolved to Base::b
so 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 main
was 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>
.
回答by zabulus
you should rewrite your Derived::ctor as follows:
你应该重写你的 Derived::ctor 如下:
Derived(double _b)
:Base(_b)
{}
And remove filed b
in Derived class. Instead mark b
in the Base
class as protected.
并删除b
派生类中的归档。而是b
在Base
类中标记为受保护。
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()