旧:如何通过CRTP基类覆盖虚函数?
struct I { virtual void foo() = 0; };
template<class D>
struct B { void foo() { } }; // provides implementation of foo in D
struct D : I, B<D> { }; // D has an implementation of foo that should override I
int main() { D d; }
Error: unimplemented pure virtual method 'foo' in 'D'
更简单:如何在不在派生类型中重新实现虚拟函数的情况下覆盖虚函数? (我想这个问题违背了虚函数的定义)。
struct I { virtual void foo() = 0; };
struct B { void foo() { } };
struct D : B, I { };
int main() { D d; }
答案 0 :(得分:2)
除了明显但笨重的void foo() { B::foo(); }
解决方案之外,您可以将“实现foo
”界面与更完整的界面I
分开:
struct FooInterface {
virtual ~FooInterface() {}
virtual void foo() = 0;
};
struct I : public virtual FooInterface {};
template<class D>
struct B : public virtual FooInterface { void foo() { } };
struct D : I, B<D> {};
int main() { D d; }
答案 1 :(得分:1)
你不必要地混合两个不同的概念:crtp,并继承虚函数的实现
crtp用于编译时多态性,运算符多态性的虚函数
说,你可以在虚拟继承层次结构中通过 dominance 继承虚函数的实现,这大致产生java / c#实现继承的效果
示例:
struct tutti_i
{
virtual int frutti() const = 0;
};
struct tutti_impl_1
: virtual tutti_i
{
int frutti() const override { return 42; }
};
struct base
: virtual tutti_i
{};
struct derived
: base
, tutti_impl_1
{};
#include <iostream>
int main()
{
tutti_i&& tutti = derived();
std::cout << tutti.frutti() << std::endl;
}
答案 2 :(得分:1)
您可以将D::foo()
实现为调用B<D>::foo()
的简单包装器。如果你有很多需要这样做的地方,你可以制作一个宏来帮忙,比如:
#define WRAP(CLASS, METHOD) \
METHOD() { return CLASS::METHOD(); }
struct D : I, B<D>
{
void WRAP(B<D>, foo);
};
答案 3 :(得分:0)
对于那些不关心B是否继承自I的人,你也可以按照最初的要求用CRTP实现这个:
struct I { virtual void foo() = 0; };
template <class D>
struct B : I { void foo(){ /* Do something fancy with D's type */ } };
struct D : B<D> { };
如果你需要进一步的继承以便foo的实现总是最派生的类型,你可以引入一个中间类型来消除foo的哪个实现被使用的歧义:
struct I { virtual void foo() = 0; };
template <class T>
struct B : virtual I { void foo() { /* Do something fancy with the most-derived type */ }};
struct D : B<D> { };
template <typename Base, typename Derived>
struct InheritFrom : public Base, public B<D> { void foo() { B<D>::foo(); } };
struct FurtherDerived : InheritFrom<D, FurtherDerived> { };