我创建了一个抽象类,它只有一组纯虚拟方法。有3种不同的类别,这些方法具有具体实现。混合纯虚拟和虚拟方法的类
现在,在编写上述结构之后,我发现派生类中的一些方法具有相同的实现。所以,我将这些功能的逻辑移到了我的基类中,并使它们变为虚拟而不是纯虚拟。现在,实现不需要在派生类中重复。这编译和执行良好。
我的基类是纯虚拟方法和虚拟方法的混合体,是否遵循像这样的结构是一种很好的设计方法?
我创建了一个抽象类,它只有一组纯虚拟方法。有3种不同的类别,这些方法具有具体实现。混合纯虚拟和虚拟方法的类
现在,在编写上述结构之后,我发现派生类中的一些方法具有相同的实现。所以,我将这些功能的逻辑移到了我的基类中,并使它们变为虚拟而不是纯虚拟。现在,实现不需要在派生类中重复。这编译和执行良好。
我的基类是纯虚拟方法和虚拟方法的混合体,是否遵循像这样的结构是一种很好的设计方法?
是的,那很好。但是:如果这些都是您拥有的类,则不需要使基类实现virtual
。
ITYM,如果这些都是你将有的派生类。 ;-) –
是的,没有。如果这些类是公共API的一部分,或者可能需要二进制向后兼容性,那么设计时应考虑到未来('虚拟')。否则,如果需求改变,您可能会在稍后使方法虚拟 –
它的精绝,虽然模式似乎已经出现,你会把所有和仅您纯虚函数的类被视为更大的接口的。
然后,您将定义一个类实现该接口的“常见”部分,并让您的3个类继承该类。
随着时间的推移,它似乎适用于更具扩展性且易于维护的代码。
Java,出于兴趣,非常强制使用这种模式。
显然,这取决于类之间的关系。换句话说,这是一个设计或实施选择(即,只要你能合理地证明它)就可以。从技术上讲,没有什么能够阻止一个班级混合使用虚拟的,纯虚拟的,非虚拟的和静态的成员函数。
如果两个派生类重写继承的虚函数并以相同的方式实现它,那么 - 是的 - 我会认真考虑将该函数提供给基类。然而,我会问更多的问题 - 例如,所有派生类是否对默认实现该函数是有意义的。从代码重用的角度来看,这样的事情可能是有道理的。从设计的角度来看,它可能不是。也就是说,如果将函数的特定实现视为“默认”(即,所有派生类默认使用该函数,除非它们覆盖该函数),那么将该定义放入一个基类。
的粗例子,你认为是没有意义的东西,认为这
class Aircraft
{
public:
virtual void Manoeuvre() = 0;
};
class Hornet : public Aircraft // F/A-18 hornet fighter aircraft
{
public:
void Manoeuvre();
};
class Tomcat : public Aircraft // F-14 tomcat fighter aircraft
{
public:
void Manoeuvre();
};
假设,因为我们的模型的保真度,这两个派生类有相同的Manoeuvre()
功能 - 他们都是超音速战斗机(所以可能采用类似的机动风格,尽管具有不同的参数化)。但是,这还不够他们Manoeuvre()
功能移到基类,因为有飞机不属于超音速战斗机,如
class Hercules : public Aircraft // C-130 hercules cargo plan
{
public:
void Manoeuvre();
};
在这种情况下,它没有任何意义了Hercules
继承机动超音速战斗机的能力,反之亦然。所以这是由Aircraft
类提供的。
在这种情况下,我可以考虑引入中间类,如Fighter
(其可能是Hornet
和Tomcat
,但不是Hercules
共用基座)和 - 如果我试图代表多种类型的货机的 - 可能是CargoPlane
成为这些人的共同基础。然后,Fighter
和CargoPlane
可能来自Aircraft
,但Aircraft
不提供仅对某些类型的飞机才有意义的功能。附带说明:虽然有些人声称不然,但C++并没有阻止纯虚函数实现定义(实现)。其含义是该函数必须被派生类重写,但是基类提供了一个默认定义(可以由派生类中的函数显式调用)。
为什么你认为基类只能有纯虚方法? –
是的,那绝对没问题。它仍然是一个抽象基类,只要它包含一个或多个纯虚拟因为您无法实例化它,但移动常见功能是件好事。 –
如果你真的想保持你的根接口完全纯粹(例如:完全隐藏实现在动态工厂库中的实现),你也可以实现一个从纯虚接口继承的中间BaseImpl,实现公共代码,重申其余的纯粹虚拟,具体的决赛可以从*继承*。 – WhozCraig