did*_*dac 4 c++ inheritance abstract
在尝试重用不同类的代码时,我偶然发现了一个问题.我在这里发帖,希望你们中的一些人能够帮助我.
我有一组派生自同一个类(A)的类(B,C),这些类强制执行某些方法(foo,run).B类实现了这些方法,B和C都提供了其他方法:
#include<iostream>
template<class I, class O>
class A {
public:
A() {}
virtual ~A() {}
virtual void foo() const = 0; // force implementation of this function
virtual void run() const = 0; // force implementation of this function
};
template<class I, class O>
class B : public A<I,O> {
public:
B() {}
virtual ~B() {}
virtual void foo() const { // implementation for the Base class
std::cout << "B's implementation of foo" << std::endl;
}
virtual void run() const { // implementation for the Base class
std::cout << "B's implementation of run" << std::endl;
}
virtual void foobar() const { // some other function provided by this class
std::cout << "B's implementation of foobar" << std::endl;
}
};
template<class I, class O, class M>
class C : public A<I,O> {
public:
C() {}
virtual ~C() {}
virtual void bar(M m) const { // some other function provided by this class
std::cout << "C's implementation of bar with: " << m << std::endl;
}
};
Run Code Online (Sandbox Code Playgroud)
现在,我想要做的是从B和C继承,以便我可以拥有额外的方法(foobar,bar),但也不必从A类(foo)实现该方法,因为它已经在B中定义:
template<class I, class O>
class D : public B<I,O>, public C<I,O,int> {
public:
D() {}
void run() const {
this->bar(123);
this->foo();
this->foobar();
}
};
Run Code Online (Sandbox Code Playgroud)
但由于某种原因,编译器给了我这个错误:
test.cpp:在函数'int main(int,char**)'中:test.cpp:68:35:error:无法分配抽象类型'D <float,double>'的对象
一个<float,double>*d = new D <float,double>(); // 我需要做什么
test.cpp:48:11:注意:因为以下虚函数在'D <float,double>'中是纯粹的:
D类:公共B <I,O>,公共C <I,O,int> {
Run Code Online (Sandbox Code Playgroud)^
test.cpp:9:22:注意:void一个<I,O> :: foo()const [with I = float; O =双]
virtual void foo()const = 0; //强制执行此功能
这是我用来运行它的代码:
int main(int argc, char **argv)
{
A<float, double> *b = new B<float, double>();
b->foo(); // prints "B's implementation of foo"
b->run(); // prints "B's implementation of run"
//A<float, double> *c = new C<float, double, int>(); // obviously fails because C does not implement any of A's functions
//A<float, double> *d = new D<float, double>; // line 68: what I need to do
//d->run(); // ***throws the abstract class error
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想从指向A的指针使用D类对象的'run'函数.由于所有函数都是虚函数,我希望执行在最低继承点中定义的每个函数的实现,这意味着'B :: run '将被丢弃.由于'D :: run'使用来自B和CI的函数,因此需要从这两个类继承.
我希望我已经足够描述它并且不会混淆任何人.谢谢您的帮助!
如果您更改B
并C
虚拟继承A
模板类,它们将在合并时共享一个基本实例,D
并且此错误将消失:
template<class I, class O>
class B : virtual public A<I,O> {
// ...
template<class I, class O, class M>
class C : virtual public A<I,O> {
Run Code Online (Sandbox Code Playgroud)
然而,这种模式(称为钻石继承(反)模式)可能很难推理,我强烈建议尽可能避免使用它.您可能会在以后遇到更加模糊的问题.
以下是此技术的一个示例,但显示了一些乍看之下可能无法预料到的结果:
class A {
public:
virtual void foo() = 0;
};
class B : virtual public A {
public:
virtual void foo() override;
};
void B::foo()
{
std::cout << "B::foo()" << std::endl;
}
class C : virtual public A { };
class D : public B, public C { };
int main() {
D d;
C & c = d;
c.foo();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
请注意,即使您正在调用C::foo()
,这是纯虚拟的,因为只有一个A
实例,继承的纯虚函数B::foo()
通过共享A
vtable 解析.这是一个有点令人惊讶的副作用 - 您可以最终调用在表兄弟类型上实现的方法.