我有一个接口,它实现为一个带有许多纯虚拟公共方法的抽象基类.这些纯虚函数可以使用模板实现,因为子类之间的差异并不大 - 所以我的想法是使用多重继承来混合提供实现的适当模板化的助手类.但是,编译器抱怨基类是抽象的; 它没有考虑辅助混合的实现,所以认为没有实现所需的方法.
例如:
class TrivialList {
int count;
public:
TrivialList(int count) : count(count){}
virtual double Average() const=0;
int Count() const {return count;}
virtual ~TrivialList(){}
};
template<typename TIndexable> class AverageHelper {
public:
double Average() const {
TIndexable const & self = static_cast<TIndexable const &>(*this);
double sum=0.0;
for(int i=0;i<self.Count();++) sum += self.Get(i);
return sum / self.Count();
}
};
class IndexableList : public TrivialList, public AverageHelper<IndexableList> {
std::vector<double> backend;
public:
IndexableList(int count) : TrivialList(count), backend(count) { }
double & Get(int i) { return backend[i];}
double const & Get(int i) const { return backend[i];}
};
IndexableList * MakeList() {return new IndexableList(5);} //error!
// cannot instantiate abstract class
Run Code Online (Sandbox Code Playgroud)
我正在使用MSC 10.0(Visual Studio 2010); 使用g ++ 4.5,代码失败并出现类似错误.
Get 或者我项目中的真实等价物不能是虚拟的,因为它们是非常小的操作,需要内联才能获得足够的性能(想想put-pixel/get-pixel) - 所以我需要通用算法来模板而不是通用算法通过虚函数调用.
要通过模板实现混合,您需要实现抽象函数的模板从抽象基类派生.
因此,您可以通过以下方式更改代码来修复代码:
// ...
template<typename TIndexable> class AverageHelper : public TriviaList{
// ...
class IndexableList : public AverageHelper<IndexableList> {
Run Code Online (Sandbox Code Playgroud)
通常,如果要提供多个混合,可以使用虚拟继承,而不是将基类的实例相乘,或者使用链继承,如下例所示:
class Abstract {
public:
virtual void foo() = 0;
virtual void bar() = 0;
};
template<class Base>
class FooImpl : Base {
public:
void foo() { /* default foo implementation */ }
};
template<class Base>
class BarImpl : Base {
public:
void bar() { /* default bar implementation */ }
};
class Derived : public BarImpl<FooImpl<Abstract> > {
// You have both foo() and bar() implementations available
};
Run Code Online (Sandbox Code Playgroud)