考虑下面的抽象类,它将作为一个类的接口,该类将某些对象所携带的信息写入标准输出。
class FileBuilder
{
public:
virtual void build(const Object& object) = 0;
virtual ~FileBuilder() = default;
};
此时,我将注意到
Object
也是具有派生类SpecialObject
的抽象类。现在,我将如下实现SpecialFileBuilder : FileBuilder
。class SpecialFileBuilder : public FileBuilder
{
public:
void build(const SpecialObject& specialObject);
};
...
void SpecialFileBuilder::build(const SpecialObject& specialObject)
{
// Do some stuff
}
我不完全理解为什么这不可能。
SpecialFileBuilder
尊重接口FileBuilder
,并且期望FileBuilder
的任何地方都可以改为SpecialFileBuilder
。非常感谢您的帮助。当然,如果我将内容更改为以下内容,则可以使用。
void SpecialFileBuilder::build(const Object& object)
但是,在实现
SpecialFileBuilder::build()
的过程中,我需要使用以下事实:参数是SpecialObject
,而不仅仅是Object
。我应该如何进行这种设计?
最佳答案
TL; DR不,这没有任何意义。
完整版本如下。
我不完全理解为什么这不可能。
virtual void build(const Object& object) = 0;
这个声明是一个承诺。它保证
build
可以接受任何Object
作为参数。此类承诺对派生类具有法律约束力,即它们必须按照基类的规定执行承诺。请注意,声明并不保证build
可以接受某些对象,而不能接受其他对象。FileBuilder* builder = GetBuilder(); // we don't know what kind of builder it is
SpecialObject some;
builder->build(some); // must work
OtherSpecialObject some;
builder->build(other); // must work too
UnrelatedObject whatever;
builder->build(whatever); // must work as well
现在看另一个声明
void build(const SpecialObject& specialObject);
它违背了诺言。最初的承诺是坚定的。给我任何东西,我可以处理。新的承诺是微弱的。哦,我是一个特殊的小建造者,我只能应付特殊的小物件!
抱歉,您不能用一个较弱的承诺来取代一个较强的承诺。如果您被允许,我们将如何信任任何诺言?
现在,如果您的设计不符合该大纲,即您始终知道您会获得哪种类型的生成器,并且您不想承诺应对所有类型的对象,那么您为该工作选择了错误的工具。也许您想尝试一下通用编程。
template <typename T>
class FileBuilder {
virtual void build (const T& t) = 0;
};
class SpecialBuilder: public FileBuilder<SpecialObject> {
void build (const SpecialObject& t) override;
};
现在上面的代码将无法正常工作,我们需要对其进行修复
FileBuilder<SpecialObject>* builder = GetBuilder<SpecialObject>(); // we know exactly what we want to build
SpecialObject some;
builder->build(some); // will work;
OtherSpecialObject other;
builder->build(other); // sorry that's not in the contract, won't compile