宣言共分散を転送する方法はありますか?
-
12-09-2019 - |
質問
私はこれらの抽象クラスのFoo
とBar
があるとします:
class Foo;
class Bar;
class Foo
{
public:
virtual Bar* bar() = 0;
};
class Bar
{
public:
virtual Foo* foo() = 0;
};
私は、派生クラスのConcreteFoo
とConcreteBar
を持っていることをさらに仮定します。私はcovariantlyこのようなfoo()
とbar()
メソッドの戻り値の型を改良したい:
class ConcreteFoo : public Foo
{
public:
ConcreteBar* bar();
};
class ConcreteBar : public Bar
{
public:
ConcreteFoo* foo();
};
私たちの最愛のシングルパスコンパイラはそのConcreteBar
がBar
から継承されます知らないので、これはコンパイルされません、となるようConcreteBar
は完全に合法共変戻り値の型があります。それが継承について、コンパイラは何も教えてくれないので、ConcreteBar
を宣言平野前方には、いずれか、動作しません。
これは私が一緒に暮らす必要があります++ Cの欠点ですか実際にこのジレンマを回避する方法がありますか?
解決
あなたは偽のそれは非常に簡単にすることができますが、静的型チェックを失います。あなたはdynamic_casts
でstatic_casts
を交換する場合は、コンパイラが内部的に使用しているものはありますが、あなたには、動的にも静的型チェックがありません。
class Foo;
class Bar;
class Foo
{
public:
Bar* bar();
protected:
virtual Bar* doBar();
};
class Bar;
{
public:
Foo* foo();
public:
virtual Foo* doFoo();
};
inline Bar* Foo::bar() { return doBar(); }
inline Foo* Bar::foo() { return doFoo(); }
class ConcreteFoo;
class ConcreteBar;
class ConcreteFoo : public Foo
{
public:
ConcreteBar* bar();
protected:
Bar* doBar();
};
class ConcreteBar : public Bar
{
public:
ConcreteFoo* foo();
public:
Foo* doFoo();
};
inline ConcreteBar* ConcreteFoo::bar() { return &dynamic_cast<ConcreteBar&>(*doBar()); }
inline ConcreteFoo* ConcreteBar::foo() { return &dynamic_cast<ConcreteFoo&>(*doFoo()); }
他のヒント
静的な多型は、あなたの問題を解決していませんか? テンプレート引数によって派生クラスで基本クラスを給餌? だから、基本クラスは、派生タイプを知っているし、適切な仮想を宣言するのでしょうか?
あなたが宣言することはできません以来ので
共分散は、継承図に基づいています。
class ConcreteBar : public Bar;
共分散についてコンパイラに指示するので、決してます。
しかし、あなたはテンプレートの助けを借りてそれを行うことができ、ConcretFooを宣言::テンプレートとそれ以降の境界などのバーは、あなたがこの問題を解決することができます。
これはどうます。
template <class BarType>
class Foo
{
public:
virtual BarType* bar() = 0;
};
template <class FooType>
class Bar
{
public:
virtual FooType* foo() = 0;
};
class ConcreteBar;
class ConcreteFoo : public Foo<ConcreteBar>
{
public:
ConcreteBar* bar();
};
class ConcreteBar : public Bar<ConcreteFoo>
{
public:
ConcreteFoo* foo();
};
所属していません StackOverflow