C ++でプライベートベースクラスにキャストを実装する方法
-
03-10-2019 - |
質問
C ++でプライベートベースクラスにキャストを実装する方法は?友達を追加するなどのハッキングを使用したくありません。公開キャスティングオペレーターの定義は機能しません。
編集 :
たとえば、私は持っています:
class A {
//base class
}
class AX : private A {
//a child
}
class AY : private A {
//another specialized child
}
class B {
//base class
void do (A a) {//do
}
}
class BX : private B {
//a child
void do (AX a) {
B::do( static_cast <A> (a) );
}
}
class BY : private B {
//another specialized child
void do (AY a) {
B::do( static_cast <A> (a) );
}
}
編集2
なぜ私はこれをするのですか?
非常にヘビー級であり、いくつかの類似したタイプ(VelocityX Velocityなど)がある可能性があるいくつかのプロパティを定義する必要があるとします。次に、これらのプロパティのセットを持つことができるクラスを作成できるようになりたいと思います。これらのプロパティを処理したい場合は、バリエーションごとに実装を追加するよりも、ベースタイプにキャストすることは明らかです。私は、プライベートインターフェイスを暗黙的に見えるよりも、必要に応じて明示的にキャストする方が良いので、私は公開を使用しません。本当の問題ではありませんが、解決策が欲しいです:)
解決
パブリックキャスティングオペレーターを定義しても機能しない場合は、通常の機能で試すことができます。
class D: private B {
public:
B& asB() { return static_cast<B&>(*this); }
};
...
D d;
d.asB().methodInB();
...
とにかく、ポイントは何ですか?もしも D
個人的に派生します B
, 、その後、あなたはaを使用することになっていません D
として B
外部から。
他のヒント
Cスタイルのキャストを使用できます。 「ハッキング」や「実装」は必要ありません。それを明示的な関数に包むと、「Cスタイルのキャストは悪い」人々に役立ちます
template<typename Targ, typename Src>
typename boost::enable_if<boost::is_base_of<Targ, Src>, Targ>::type &
private_cast(Src &src) { return (Targ&)src; }
キャストを安全にするには、それを確実にする必要があります Targ
実際にはプライベートまたはパブリックベースです。これはによって行われます boost::is_base_of
.
もちろん、そのようなキャストを行う代わりに、ベースポインターを返す、それぞれの派生クラスのメンバー関数を好む必要があります。.
公共鋳造オペレーターの定義は機能しません。
それは私には意味がありません...なぜベースクラスをプライベートにするのですか?公開するだけです。コンバージョン機能が機能しない理由は、標準では、暗黙の変換が基本クラス、クラス自体、または void
.
私はこれのためのユースケースを持っています。私は常に機能を追加している大規模で揮発性の基本クラスから継承していますが、サブクラスで正しく機能する基本クラスの関数はほとんどないので、個人的に継承しています。
基本クラスを返す関数を作成するだけで最も簡単だと思います。以下に、完全に修正されたプログラムをリストします。質問を送信する前にコードをコンパイルしてみてください。「do」のような識別子を関数名として使用すると、すべてのコンパイラが不幸になる可能性が高いためです。
class A {
//base class
};
class AX : private A {
//a child
public:
A *ToA() { return this; }
};
class AY : private A {
//another specialized child
public:
A *ToA() { return this; }
};
class B {
//base class
protected:
void do_it (A a) {};
};
class BX : private B {
//a child
void do_it (AX a) {
B::do_it( *a.ToA() );
}
};
class BY : private B {
//another specialized child
void do_it (AX a) {
B::do_it( *a.ToA() );
}
};