2

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

4 回答 4

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; }
于 2013-02-26T14:37:52.593 回答
1

您不必要地混合了两个不同的概念:crtp 和继承虚函数的实现

crtp 用于编译时多态,虚函数用于运行时多态

也就是说,您可以通过在虚拟继承层次结构中占主导地位来继承虚拟函数的实现,这大致产生了 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;
}
于 2013-02-26T14:31:54.897 回答
1

您可以实现D::foo()为一个简单的包装调用B<D>::foo(). 如果你有很多地方需要这样做,你可以做一个宏来帮忙,比如:

#define WRAP(CLASS, METHOD) \
    METHOD() { return CLASS::METHOD(); }

struct D : I, B<D>
{
    void WRAP(B<D>, foo);
};
于 2013-02-26T14:36:41.833 回答
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> { };
于 2016-08-24T05:34:21.107 回答