如何让派生类使用基类实现来满足接口
How to have a derived class use the base implemention to satisfy an interface
我有以下两个接口,它们不属于继承层次结构。然后我有两个具体的类,其中一个派生于另一个。
class ICar {
public:
virtual void drive() = 0;
};
class IFastCar {
public:
virtual void drive() = 0;
virtual void driveFast() = 0;
};
class Car : public virtual ICar {
public:
void drive() {};
};
class FastCar : public Car, public virtual IFastCar {
public:
void driveFast() {};
};
int main()
{
FastCar fc;
fc.drive();
fc.driveFast();
return 0;
}
当我编译时,我得到以下错误:
error: cannot declare variable `fc' to be of type `FastCar'
error: because the following virtual functions are abstract:
error: virtual void IFastCar::drive()
如果我在FastCar中编写一个函数将drive()委托给基类
,我的程序将工作。void drive() { Car::drive(); }
是可能有FastCar编译没有编写方法委托给基类?
注意:ICar和IFastCar是由两个不同的团队创建的,属于两个不同的项目。团队已经就共享操作的通用方法签名达成一致。我在实现类中使用继承来尝试重用实现中相同的部分。
问题在于这里发生了多重继承…尽管FastCar
是从Car
派生出来的,但Car
基类中的drive()
版本只覆盖ICar::drive()
,而不是IFastCar::drive()
。因此,由于您是从IFastCar
派生FastCar
,因此需要在某些时候在FastCar
中定义一个函数,该函数也覆盖纯虚拟抽象方法IFastCar::drive()
…继承的Car::drive()
不会自动覆盖IFastCare::drive()
,因为它不继承那个类。IFastCar::drive()
和ICar::drive()
是两个不同的纯抽象虚函数,需要分别重写。如果你想让IFastCar::drive()
的接口调用你继承的Car::drive()
函数,那么你需要委托这个继承的函数,就像你在FastCar::drive()
的一个版本中所做的那样,这个版本专门调用drive()
的基类版本。
问题是Car
不实现IFastCar::drive
,而只实现ICar::drive
。第一个设计问题是为什么IFastCar
不扩展ICar
接口并重新定义相同的操作?
如果由于某种原因这不是一个选项,那么你可以做的最简单的事情是通过将请求转发到Car::drive
方法来实现FastCar
中的IFastCar::drive()
:
void FastCar::drive() {
Car::drive();
}
您在这里使用virtual
继承是虚假的,并且是转移注意力的。virtual
继承仅用于从公共基类派生一次;not只引入一个声明来匹配成员签名。
所以,你的FastCar
具体类实际上有3个成员,而不是2个:
virtual void ICar::drive()
virtual void IFastCar::drive()
virtual void IFastCar::driveFast()
两个不同的drive()
似乎是相关的,所以你的设计似乎是有缺陷的。您不希望virtual
继承—您可能希望IFastCar
从ICar
派生。
class ICar {
public:
virtual void drive() = 0;
};
class IFastCar : public ICar {
public:
virtual void driveFast() = 0;
};
class Car : public virtual ICar {
public:
void drive() {};
};
class FastCar : public IFastCar {
public:
void drive() {};
void driveFast() {};
};
int main()
{
FastCar fc;
fc.drive();
fc.driveFast();
return 0;
}
如果您希望Car
实现FastCar
将采用的一些基本功能,那么您可以从Car
派生FastCar
,并且就是您希望继承virtual
的原因。只要记住在菱形顶部下方的位置应用virtual
继承:
class ICar {
public:
virtual void drive() = 0;
};
class IFastCar : virtual public ICar {
public:
virtual void driveFast() = 0;
};
class Car : public virtual ICar {
public:
void drive() {};
};
class FastCar : public IFastCar, public Car {
public:
void driveFast() {};
};
int main()
{
FastCar fc;
fc.drive();
fc.driveFast();
ICar* fc_a = new FastCar;
fc_a->drive(); // invokes Car::drive() via domination
return 0;
}
如果你编译&运行上述代码,您将获得所需的行为,但代价是编译器警告。在MSVC10上它是:
1>main.cpp(19): warning C4250: 'FastCar' : inherits 'Car::Car::drive' via dominance
1> main.cpp(13) : see declaration of 'Car::drive'
这是一个警告,表明您的实现继承体系结构可能搞砸了。事实上,在大多数情况下,它可能是(尽管在这种情况下不是)。这可能很快就会让人感到非常困惑,特别是对于多年后试图弄清楚代码的维护程序员来说。为了消除这种混淆并避免所有编译器警告,我更倾向于(作为规则)将委托给姊妹类而不是实现继承。
class ICar {
public:
virtual void drive() = 0;
};
class IFastCar : virtual public ICar {
public:
virtual void driveFast() = 0;
};
class ICarImpl
{
public:
void drive_impl() {};
};
class IFastCarImpl
{
public :
void driveFast_impl() {};
};
class Car : public virtual ICar, protected ICarImpl {
public:
void drive() { drive_impl(); }
};
class FastCar : public IFastCar, protected ICarImpl, protected IFastCarImpl {
public:
void driveFast() { driveFast_impl(); }
void drive() { drive_impl(); }
};
int main()
{
FastCar fc;
fc.drive();
fc.driveFast();
ICar* fc_a = new FastCar;
fc_a->drive();
return 0;
}
这完成了实现继承的通常目标——只保留一组公共代码,可以跨多个具体类共享,使维护更容易。
因为ICar和IFastCar都是汽车,你可以让IFastCar派生自ICar,然后像你一样实现Car和FastCar。
class ICar {
public:
virtual void drive() = 0;
};
class IFastCar : ICar
{
public:
virtual void drive() = 0;
virtual void driveFast() = 0;
};
class Car : ICar {
public:
void drive()
{
cout << "driving a normal car" << endl;
}
};
class FastCar : IFastCar
{
public:
void drive()
{
cout << "driving a fast car the normal way" << endl;
}
void driveFast()
{
cout << "driving a fast car at top speed" << endl;
}
};
int main()
{
FastCar fc;
fc.drive();
fc.driveFast();
return 0;
}
- 如何正确实现与基类不同的版本?
- 可以具有不同基成员实现的类的最佳实现
- 对派生自同一基类的类实现冲突检查
- 无法使用在子类中定义的虚拟getter实现基类
- 关于C++从派生类调用在基类中实现的虚拟函数的问题
- 如何在基类中定义静态接口,并确保该接口必须在派生类中实现
- 如何在CRTP实现中传递基类指针
- 有没有一种方法可以使用SFINAE来检测一个类型是否实现了给定的抽象基类
- C++ 多重继承:使用基类 A 的实现实现基类 B 的抽象方法
- 如何在子类中重写时调用私有虚拟基类实现
- 如何在基类中实现子类迭代器的统一接口?
- 调用基类克隆实现
- 检查实现哪些基类
- 我如何实现从其基类获取变量的构造函数
- 什么更有效率?在重载函数中或通过在基类函数中检查对象类型来实现
- 如何在抽象基类中实现运算符+
- 将多态性与运算符 + 重载模板化类结合使用.如何实现基类?
- 如何私下从基类的导数继承,但实现基类的公共接口?
- 从派生类实现基类构造函数专用化的替代方法是什么
- 实现基类方法来访问派生类的属性