2017-01-10 97 views
1

我创建了一个抽象类,它只有一组纯虚拟方法。有3种不同的类别,这些方法具有具体实现混合纯虚拟和虚拟方法的类

现在,在编写上述结构之后,我发现派生类中的一些方法具有相同的实现。所以,我将这些功能的逻辑移到了我的基类中,并使它们变为虚拟而不是纯虚拟。现在,实现不需要在派生类中重复。这编译和执行良好。

我的基类是纯虚拟方法和虚拟方法的混合体,是否遵循像这样的结构是一种很好的设计方法?

+1

为什么你认为基类只能有纯虚方法? –

+0

是的,那绝对没问题。它仍然是一个抽象基类,只要它包含一个或多个纯虚拟因为您无法实例化它,但移动常见功能是件好事。 –

+2

如果你真的想保持你的根接口完全纯粹(例如:完全隐藏实现在动态工厂库中的实现),你也可以实现一个从纯虚接口继承的中间BaseImpl,实现公共代码,重申其余的纯粹虚拟,具体的决赛可以从*继承*。 – WhozCraig

回答

0

是的,那很好。但是:如果这些都是您拥有的类,则不需要使基类实现virtual

+2

ITYM,如果这些都是你将有的派生类。 ;-) –

+1

是的,没有。如果这些类是公共API的一部分,或者可能需要二进制向后兼容性,那么设计时应考虑到未来('虚拟')。否则,如果需求改变,您可能会在稍后使方法虚拟 –

5

它的精绝,虽然模式似乎已经出现,你会把所有纯虚函数的类被视为更大的接口的。

然后,您将定义一个类实现该接口的“常见”部分,并让您的3个类继承该类。

随着时间的推移,它似乎适用于更具扩展性且易于维护的代码。

Java,出于兴趣,非常强制使用这种模式。

1

显然,这取决于类之间的关系。换句话说,这是一个设计或实施选择(即,只要你能合理地证明它)就可以。从技术上讲,没有什么能够阻止一个班级混合使用虚拟的,纯虚拟的,非虚拟的和静态的成员函数。

如果两个派生类重写继承的虚函数并以相同的方式实现它,那么 - 是的 - 我会认真考虑将该函数提供给基类​​。然而,我会问更多的问题 - 例如,所有派生类是否对默认实现该函数是有意义的。从代码重用的角度来看,这样的事情可能是有道理的。从设计的角度来看,它可能不是。也就是说,如果将函数的特定实现视为“默认”(即,所有派生类默认使用该函数,除非它们覆盖该函数),那么将该定义放入一个基类。

的粗例子,你认为是没有意义的东西,认为这

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(其可能是HornetTomcat,但不是Hercules共用基座)和 - 如果我试图代表多种类型的货机的 - 可能是CargoPlane成为这些人的共同基础。然后,FighterCargoPlane可能来自Aircraft,但Aircraft不提供仅对某些类型的飞机才有意义的功能。附带说明:虽然有些人声称不然,但C++并没有阻止纯虚函数实现定义(实现)。其含义是该函数必须被派生类重写,但是基类提供了一个默认定义(可以由派生类中的函数显式调用)。