我有以下困境:
我有一个完整的抽象类。每个继承类都需要3个相同的参数。它们中的每一个还需要其他特定参数。
我可以:
1)实现一个通用的构造函数来初始化我的基类中的3个公共参数,但是我必须为相应的字段制作非抽象的getter(它们是私有的)。
OR
2)保留我的基类摘要并在继承的类中实现构造函数,但是我必须在每个类字段中为公共参数创建它。
哪种方法更好?我不想使用受保护的成员。
答案 0 :(得分:3)
抽象类是至少有一个纯虚拟(或称为抽象)函数的类。只要具有至少一个纯虚函数,具有非抽象的非虚函数并不会改变您的类是抽象的这一事实。去拥有基类中的通用功能,即使它是抽象的。
答案 1 :(得分:0)
如果你的类看起来像这样,那就是一个纯粹的抽象类:
class IFoo {
public:
virtual void doThings() = 0;
}
class Foo {
public:
Foo(std::string str);
void doThings() override;
}
继承的价值在于为您提供在运行时将Foo替换为另一个的机会,但隐藏在接口后面的具体实现。你不能在构造函数中使用这个优势,没有虚拟构造函数(这就是Abstract Factory Pattern之类的东西存在的原因)。您Foo
的所有实现都需要std::string
,而doThings
的所有实现都使用该字符串?太好了,但这不是合同的巧合,也不属于IFoo
。
让我们谈谈你是否在IFoo
中创建了具体的实现,这样它就是一个抽象类而不是一个纯抽象类(IFoo
现在是一个坏名字btw)。 (* 1)让我们假设使用继承来共享行为是您的正确选择,这有时是正确的。如果类具有需要初始化的字段,则创建一个protected
构造函数(从每个子实现中调用)并删除/省略默认值。
class BaseFoo {
private:
std::string _fooo;
protected:
BaseFoo(std::string fooo) : _fooo(fooo) {}
public:
virtual void doThings() = 0;
std::string whatsTheBaseString() { return _fooo;}
}
以上是从子构造函数正确传递基类所需字段的方法。这是一个编译时保证,子类将“记住”正确初始化_fooo
并避免将实际成员fooo
暴露给子类。尝试在所有子构造函数中直接初始化_fooo
在这里是不正确的。
* 1)很快,为什么? Composition may be a better tool here?
答案 2 :(得分:0)
避免代码重复而不用数据成员污染抽象接口的一种方法是引入额外的继承级别:
<?xml version="1.0" encoding="utf-16"?>
<OrdersContainer>
<Orders>
<Order Sequence="1">
<Name>Order 1</Name>
</Order>
<Order Sequence="2">
<Name>Order 2</Name>
</Order>
</Orders>
</OrdersContainer>