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;
};
我有一个特定的 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;
};