我有一个代码片段如下:
#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.因为我认为无论是Base和Derived需要访问这个领域,我定义了一个get在成员函数Base,因此Derived可以继承它.然后我尝试从不同的对象获取成员字段.
结果表明,我仍然得到原b在Base通过d.get()的而不是在Derived,这就是我所期待的代码来执行.代码(或我的理解)有什么问题吗?是否在规范中指定了此行为?覆盖成员字段并正确定义其getter和setter的正确方法是什么?
mas*_*oud 14
b派生类中添加的新内容不会覆盖base b.它只是隐藏它.
因此,在派生类中,您有两个b并且虚拟方法打印对应b.
您不能简单地覆盖成员字段,并且在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)
| 归档时间: |
|
| 查看次数: |
34815 次 |
| 最近记录: |