2

Old: 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

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 に答える
1

crtp と仮想関数の実装の継承という 2 つの異なる概念を不必要に混在させています。

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 に答える
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 に答える