重写派生类中的成员字段
Override member field in derived classes
我在下面有一个代码片段:
#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;
}
运行编译的可执行文件,我发现结果超出了我在llvm-g++ 4.2机器上的预期。我的盒子上的输出是
Hello from Derived with b: 10
Derived b: 0
Hello from Base with b: 0
Base b: 0
我想在代码中做的是覆盖Derived
类中的成员字段(b
(。由于我认为Base
和Derived
都需要访问此字段,因此我在Base
中定义了一个get
成员函数,因此Derived
可以继承它。然后我尝试从不同的对象获取成员字段。
结果表明,我仍然通过d.get()
获得Base
的原始b
,而不是Derived
中的原始,这就是我期望代码做的事情。代码(或我的理解(有什么问题吗?规范中是否指定了此行为?覆盖成员字段并正确定义其 getter 和 setter 的正确方法是什么?
生类中添加的新b
不会覆盖 base 的b
。它只是隐藏它。
因此,在派生类中,您有两个b
并且虚拟方法打印相应的b
。
不能简单地重写成员字段,并且在编译Base::get
时,b
变量解析为Base::b
,因此此方法将始终使用此值,而不是派生类中具有相同名称的另一个字段中的值。
属性的常用方法是覆盖访问它的方式,即覆盖访问器(getter 和 setter(。
您可以通过装饰吸气剂来实现类似的东西,但吸气剂返回类型将始终相同:
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;
};
我不确定我是否正确理解了您,但是"覆盖"的意思是"替换",您将使用模板:
#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;
}
您在main
中编码也尝试Base b = d;
会导致切片,上述修复并确保您不会意外使用Base<int>
而不是Base<double>
。
现场示例
你应该重写你的 Derived::ctor,如下所示:
Derived(double _b)
:Base(_b)
{}
并删除派生类中的归档b
。而是将Base
类中的b
标记为受保护。
编辑
忽略所有这些我发现您的代码中有问题:
Base b = d;
您正在将派生对象复制到基。它仅复制基本字段。如果你想要多态性,请尝试下一步:
Base *b = &d;
b->get()
- C++:用户定义的类,以成员字段作为地址
- 用于基于成员字段或函数创建比较器的快捷方式
- uninit_member:非静态类成员字段 m_cJobState.bstatus 未在此构造函数中初始化,也不在其调
- 派生类中的成员字段别名(无访问器功能)
- 如何使用 Clang 查找所有成员字段读/写?
- C 模板功能在任何集合成员字段上迭代
- 一次启用 MANY 类的成员字段,具体取决于模板<T>
- 如何在C++的专用模板类中访问模板类成员字段
- 动态链接到 c++ 静态成员字段时符号查找失败
- std :: async在成员字段的成员功能上
- C++使用成员字段设置比较器
- C++11 是否重新初始化初始化的成员字段
- 将控件作为成员字段传递给使用新 connect() 调用的方法
- 构造以shared_ptr作为成员字段的类的正确语法是什么
- 成员字段的 getter 的常用做法是什么?
- c++:对于多重继承类的子类中的重复成员字段,什么是好的重构
- C++ -- 将元素添加到私有成员字段 std::vector
- 重写派生类中的成员字段
- 在C++类中使用指针作为成员字段是不是很傻
- 模板继承成员字段