告诉子类对超类的受保护变量执行某些操作是否是一种好的做法(也许是一些已知的设计模式?)?
is it a good practice (maybe some known design pattern?) to tell subclasses to do something to the superclass's protected variables?
这是一个好模式吗?
BaseClass {
protected:
Data m_data;
public:
Interesting public_method() {
//returns something interesting about m_data
//what exactly depends on what the subclass put into m_data
}
}
DerivedClass {
public:
DerivedClass() { //properly populate m_data }
}
这样做的缺点是,事情太"松散",并且没有强制编译时间,因为子类程序员只是被告知要做一些事情,而不是真正被迫去做,所以我想知道经验丰富的c++程序员是否认为这是一种好的做法。
有什么好办法或更好的办法吗?
如果只有超类构造函数可以在子类构造函数完成工作后被强制调用。然后超类构造函数可以在中包含所需的参数
c++不允许这样做:(
如果只有超类构造函数可以在子类构造函数完成工作后被强制调用。然后超类构造函数中可以包含所需的参数
ctor初始值设定项列表非常强大。虽然只能使用表达式,但这些表达式可以包括函数调用。实际上,在构造函数主体中可以做的任何事情都可以从初始值设定项列表中实现。
当然,你必须尊重构造顺序,所以在初始化基类之前不能在基类上调用成员函数。但在初始化成员时可以访问基类。
class BaseClass
{
Data m_data;
protected:
BaseClass( Data&& data ) m_data(data) {}
public:
Interesting public_method() {
//returns something interesting about m_data
//what exactly depends on what the subclass put into m_data
}
};
class DerivedClass : public BaseClass
{
static Data make_arg_into_data( const T& arg ) { /* calculate and return the right value for m_data */ }
static Interesting make_arg_into_member_init( BaseClass* pThis, const T& arg ) { return pThis->public_method(); }
V m_member;
public:
DerivedClass( T arg ) BaseClass(make_arg_into_data(arg)), m_member(make_arg_into_member_init(this, arg)) { }
};
这不是一个模式,而是一个反模式。经验法则:受保护的变量是坏的。继承的行为(通常从具体类继承)是不好的。当然,有时可能有理由忽视这两种情况,但如果你不说你真正想做什么,就很难说了。
在我看来,永远不应该使用受保护的变量。我更喜欢使用带有受保护方法的私有变量。通过这种方式,如果你想使用一个polymorfic对象,你可以覆盖你的方法,避免"坏的惊喜"。如果你的类是final
,当然你可以直接使用受保护的var.
对我来说,这听起来不太正确。虽然派生类调用基类并非闻所未闻,但更常见的情况是,派生类会覆盖(虚拟)public_method
来提供该信息。
或者,按照建议,使用工厂函数。或者是一个静态的"构造函数"成员函数,所以不调用new,而是调用一个调用new
和special function to make set the data
的函数。
所有可能的解决方案。
听起来你可以使用一个工厂:
BaseClass {
private:
Data m_data;
public:
void setData(const Data& data) { m_data = data; }
virtual Data generateData() = 0;
};
struct Factory
{
template<class T>
static BaseClass* getInstance()
{
BaseClass* t = new T;
t->setData(t->generateData());
return t;
}
};
并称之为
BaseClass* p = Factory::getInstance<Derived>();
正如您所看到的,非抽象派生类被迫调用generateData
,因此它们必须生成一个有效的Data
。
我只使用了原始指针以便于编写,不要:)
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 资源管理设计模式
- 用于在回调中调用解析器的设计模式
- 设计帮助 - 为不同类型的消息处理通用接口的设计模式
- 在这种情况下我应该使用哪种设计模式
- C++中物体改变识别的设计模式?
- 确保所有构造函数调用相同的函数 c++ 设计模式
- 需要实例化不同类/对象并在启动时确定的硬件插槽的设计模式
- 设计模式,以避免不必要地添加抽象函数以适应新功能
- 工厂设计模式优化
- 使用C++模板的数据映射器设计模式
- 为什么以及如何使用原型设计模式
- 具有多个继承共享一个资源的对象 - 寻找良好的设计模式
- 在C++中创建观察器设计模式的好方法
- 现代C++在多大程度上消除了对设计模式的需求?
- 对于存储另一个类所需信息的类,例如其构造,是否有设计模式?
- 下面抽象工厂设计模式的实现是正确的吗
- sql记录集函数的状态设计模式
- 是否有可以处理方法调用依赖关系的设计模式?
- 告诉子类对超类的受保护变量执行某些操作是否是一种好的做法(也许是一些已知的设计模式?)?