抽象基类是否可以使用非抽象方法?

时间:2009-12-01 09:37:55

标签: c++ coding-style

抽象基类(接口类)通常将其所有成员函数都抽象化。但是,我有几种情况,其中使用由调用接口的抽象方法组成的成员函数。我可以在派生但仍然抽象的类中实现它们,或者我可以将这些方法实现为接口类的非抽象非虚方法。

在接口类中实现方法时,设计方面是否存在任何问题?是不好的风格,如果是这样,为什么?

静态方法是否也一样?

例如

class IFoo
{
    public:
    virtual ~IFoo();
    virtual double calcThis( InputType p ) const = 0;
    virtual double calcThat( InputType p ) const = 0;
    double calcFraction( InputType p ) { return calcThis( p ) / calcThat( p ); }
    static BarType bar( InputType p );
};

class MyFoo : public IFoo
{
    public:
    // implements IFoo
    virtual double calcThis( InputType p ) const;
    // implements IFoo
    virtual double calcThat( InputType p ) const;
};

class IFoo
{
    public:
    virtual ~IFoo();
    virtual double calcThis( InputType p ) const = 0;
    virtual double calcThat( InputType p ) const = 0;
};

class FooBase : public IFoo
{
    public:
    virtual ~FooBase();
    double calcFraction( InputType p ) { return calcThis( p ) / calcThat( p ); }
    static BarType bar( InputType p );
};

class MyFoo : public FooBase
{
    public:
    // implements IFoo
    virtual double calcThis( InputType p ) const;
    // implements IFoo
    virtual double calcThat( InputType p ) const;
};

6 个答案:

答案 0 :(得分:9)

绝对。这就是template method pattern的工作方式(虽然不一定是实现接口) - 它完全可以接受,而且通常是个好主意。

Java AbstractList类就是一个很好的例子。

编辑:抱歉没有回复过。您的calcFraction方法在我看来就像是模板方法模式的实现 - 它是基于调用抽象方法的具体实现。

现在我同意DrPizza - 如果你正在调用某个接口,它实际上不应该有任何实现。可以使抽象基类具有非抽象方法(根据您的问题标题),但我不认为“抽象基类”和“接口类”是等价的。这可能是我的C#和Java背景,您可以将类型声明为接口 - 但是不能提供任何实现。

答案 1 :(得分:2)

如果你将它称为一个接口(即你似乎是通过使用命名约定“IFoo”),那么它应该是一个纯接口(没有实现)。

如果它只是一个抽象类,那么纯虚拟和实现方法的混合是完全合理的。

答案 2 :(得分:1)

绝对是的。这是拥有抽象类而不是接口的原因之一。

答案 3 :(得分:1)

我一直认为这是抽象类实际上的用途:实现所有后代共有的一些基本行为,但是使部件抽象为派生类特有的。

答案 4 :(得分:0)

是。在抽象基类中实现方法(虚拟或非虚拟)是完全正常的并且通常是可取的。如果你真的想要一个界面,最好使用你的第二个结构,所以读者可以清楚地使用它,但两者都是完全合法的C ++。如果存在实现,我就不会使用'I'指示符。

答案 5 :(得分:0)

我没有理由不在抽象类中进行某些实现。