C++ 抽象基类有非抽象方法可以吗?

C++ 抽象基类有非抽象方法可以吗?,c++,coding-style,C++,Coding Style,抽象基类(接口类)的所有成员函数通常都是抽象的。但是,我有几个例子,其中使用了由对接口的抽象方法的调用组成的成员函数。我可以在派生但仍然是抽象的类中实现它们,或者我可以将这些方法实现为接口类的非抽象、非虚拟方法 在接口类中实现方法在设计方面是否存在任何问题?这是一种糟糕的风格吗?如果是,为什么 静态方法也是如此吗 比如说 class IFoo { public: virtual ~IFoo(); virtual double calcThis( InputType p )

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

在接口类中实现方法在设计方面是否存在任何问题?这是一种糟糕的风格吗?如果是,为什么

静态方法也是如此吗

比如说

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;
};

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

绝对不会。这就是它的工作原理(尽管这不一定实现一个接口)——这是完全可以接受的,而且通常是一个好主意

Java类就是一个很好的例子

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


现在我同意DrPizza——如果您将某个东西称为接口,那么它实际上不应该有任何实现。抽象基类有非抽象方法(如您的问题标题),但我不认为“抽象基类”和“接口类”是等价的。这可能是我的C#和Java背景,您可以将类型声明为接口,但无法提供任何实现。

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

我不认为在抽象类中没有实现的理由。

我一直认为抽象类的实际用途是:实现所有后代共同的一些基本行为,但是要将派生类特定的部分抽象化。

如果您将其称为接口(即,您使用命名约定“IFoo”时似乎是接口),那么它应该是纯接口(无实现)


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

有趣的一点,但模板方法(或策略模式,或非虚拟接口)恰恰相反,不是吗?这将是一个面向实现的类,很可能包含数据成员和所有成员,它们将其部分实现委托给派生类。我在想萨特在本例中的文章:你能更具体/详细地说明为什么我应该让它成为一个纯界面吗?这仅仅是惯例还是有其他惩罚?按照惯例,被标记为接口的东西是“纯粹的”。有些情况下,我怀疑你的接口必须是纯的,比如COM,但是如果你只是写C++,那就取决于你。在编写接口时,是否存在对每个实现者都有用的通用功能?如果是这样,那么将其设置为抽象类。如果不是——如果每个实现都会有本质上的不同——那么就选择纯接口。请记住这纯粹是一个你称之为“接口”的问题:“接口”通常只是指“没有函数实现的抽象类”。一种选择是将类拆分为一个基类,其中只包含纯虚拟函数(您称之为“接口”),另一个基类从中派生并实现其中一些函数(您称之为“mixin”)。mixin的作用是允许具体类只实现少量函数。但您也可以允许具体类自己完成所有工作,而不是从mixin派生。。。。这是因为从抽象类继承,然后重写所有非纯函数和纯函数,充其量是没有意义的,如果有人假设一个函数的所有实现都具有基类实现恰好具有的某些特定性能特征,那么最坏的情况可能会误导某人或导致错误。