C++ 接口可以从 class 继承并具有完整的实现吗?

Can a C++ interface inherit from a class with full implementation?

我有一个特定的 class 结构,尽管我觉得当项目变大时它可能会变得有点混乱。总体思路如下:

所有可能的车辆都有一个 class,其基本实现不会因任何车辆而改变,无论其具体类型如何。然后,对于所有的汽车,应该有一个只有汽车才有的功能的接口。这个接口是纯虚拟的。然后,任何汽车都可以根据需要实现这些功能。我在下面包含了一个非常简单的代码示例:

class Vehicle { //general class for a vehicle
public:
    void move() {
        std::cout << "I moved\n"; 
    }
    void crash() {
        std::cout << "I crashed\n"
    }
};

class CarInterface : public Vehicle { //purely virtual interface for cars
public:
    virtual void refuel() = 0;
};

class Ferrari: public CarInterface { //implementation: one specific car
public:
    void refuel() override {
        std::cout << "I use ferrari fuel\n"
    };
};

在c++指南中,它说你应该区分实现继承和接口继承。这仍然满足该要求吗?

Can a C++ interface inherit from a class with full implementation?

C++ 语言不区分接口和其他 classes。这种区别纯粹是约定俗成的。因此,从一个角度来看,说 C++ 接口不能 [无论如何] 是正确的,因为没有 C++ 接口这样的东西。

如果我们将接口视为一个抽象概念,那么答案取决于人们选择如何解释这个概念,并用语言来精确地指定它。如果解释是接口 class 只有纯虚成员函数(这是一种常见的解释),那么 CarInterface 不是接口,因为它通过继承具有非纯虚成员函数。


In the c++ guidelines

我想您打算参考“C++ 核心指南”。这是那里定义概念的方式:

Note Definition:

  • interface inheritance is the use of inheritance to separate users from implementations, in particular to allow derived classes to be added and changed without affecting the users of base classes.
  • implementation inheritance is the use of inheritance to simplify implementation of new facilities by making useful operations available for implementers of related new operations (sometimes called “programming by difference”).

A pure interface class is simply a set of pure virtual functions; see I.25.

这有点含糊,但我会解释说 CarInterface 接口继承和实现继承的一种形式 ,它是 不是纯界面。

在定义下方以及第 I.25 节中,指南将这种混合继承作为一个错误示例进行了说明,并建议使用纯接口作为替代方案。


你的例子可以通过使用虚拟继承来实现纯接口和重用(这就是你的 Vehicle class 大概是为了):

// pure interface
class VehicleInterface {
public:
    virtual void move() = 0;
    virtual void crash() = 0;
};

// pure interface
class CarInterface : public virtual VehicleInterface {
public:
    virtual void refuel() = 0;
};

class CommonVehicle : public virtual VehicleInterface {
public:
    void move() override;
    void crash() override;
};

class Ferrari: public CarInterface, private CommonVehicle {
public:
    void refuel() override;
};