通过CRTP基类覆盖虚函数

时间:2013-02-26 14:26:54

标签: c++ polymorphism virtual-functions crtp

旧:如何通过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; }

4 个答案:

答案 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> { };