私は2つのクラスを持っています。どちらも、ユーザ入力に基づいて同様のことをする同じ関数名を持っています。私はこのようなことをする必要があります。条件からオブジェクトを宣言し、それを残りの関数で使用できるようにするにはどうすればよいですか?
if (myapp.advanced == true)
class1 a;
else
class2 a;
しかし、aはif内部から宣言されているため、次の行では使用できません。どのように上記の状態を修正するのですか?
私は2つのクラスを持っています。どちらも、ユーザ入力に基づいて同様のことをする同じ関数名を持っています。私はこのようなことをする必要があります。条件からオブジェクトを宣言し、それを残りの関数で使用できるようにするにはどうすればよいですか?
if (myapp.advanced == true)
class1 a;
else
class2 a;
しかし、aはif内部から宣言されているため、次の行では使用できません。どのように上記の状態を修正するのですか?
これらのタイプが関連している場合は、共通の基本クラスを使用して、次の操作を行います。const
参照にバインド
const base& a = (myapp.advanced == true) ? static_cast<base&>(class1())
: class2();
a.something();
a.some_other_thing();
a.yet_another_thing();
一時は自分の寿命は、基準の生涯の終わりまで延長持っているので、これは安全です。 (あなたがオブジェクトを変更する必要がある場合、あなたはconst
と離れて行うことができます)異なる機能にを使用して、あなたが懸念オブジェクトの作成を離れた場合とオブジェクトただし、このようなハックは必要ではないでしょう。
void do_something(base& obj)
{
obj.something();
obj.some_other_thing();
obj.yet_another_thing();
}
if (myapp.advanced == true) {
class1 a;
do_something(a);
} else {
class2 a;
do_something(a);
}
種類が無関係であれば、あなたはまだ関数テンプレートにdo_something()
を回すことによってこれを行うことができます:
template< class T >
void do_something(T& obj)
{
obj.something();
obj.some_other_thing();
obj.yet_another_thing();
}
if (myapp.advanced == true) {
class1 a;
do_something(a);
} else {
class2 a;
do_something(a);
}
@sbi:はい、私はあなたが別のものを追加したとコメントして気づいた後、気にしません。 Btwの場合、 'class1()'と 'class2()'は同じ型を持たないので、三項式はキャストなしではコンパイルされません。それらのうちの1つは 'const base&'にキャストする必要があります。 –
@sgolodetz:そうだね、これを指摘してくれてありがとう!それを私が直した。 – sbi
もう1つの問題は、偶然にも、最初のメソッドは、オブジェクトが 'const'であれば動作するということです。非const参照に一時的にバインドすることはできないからです。しかし、彼らが「const」であることがうまくいけば、これは物事について行く良い方法です。 –
私は、基本クラスにpure virtualとしてput function something()を置き、class1とclass2を継承することをお勧めします。ここで
class Base
{
public:
virtual void something() = 0;
virtual ~Base(){}; // since we use Base class pointer the destructor should be virtual
};
class class1 : public Base
{
public:
void something(){ //do stuff
}
};
class class2 : public Base
{
public:
void something(){ //do other stuff
}
};
は、この技術の使用方法のサンプルです:
int main()
{
Base* a = NULL;
if (myapp.advanced == true)
a = new class1();
else
a = new class2();
a->something();
// when the instance is not needed anymore destroy it.
delete a;
}
フレッドNurkがdelete
演算子を使用するための他の選択肢がありますコメントで述べたように - auto_ptrは、異なるブーストスマートポインタが。彼らは多くの人々(自分自身を含む)によって広く使われており、new
で作成されたオブジェクトの生活をより簡単に制御できます。 OPさんのコメント次
別の編集
:#ifndef _SOME_UNIQUE_NAME_HERE_
#define _SOME_UNIQUE_NAME_HERE_
// header body goes here
#endif
に複数回のインクルード保護マクロを置くことを忘れないでください。私は考えることができる
aを削除することを忘れないでください。 :-)基本クラスを必要としない場合は、2つのポインタを使って同じことをすることができます。そして、NULL以外のものを使って何かを呼び出します。 –
+1、これはインタフェースと2つの具体的な実装の主要候補のようです。 –
'Base :: something()'、 'class1 :: something()'、 'class2 :: something()'をpublicにして、 'Base'に仮想デストラクタを追加したいかもしれません。 –
二つの方法:
1)、クラス1とクラス2は、いくつかの基本クラスclassB
から派生してください、その後の操作を行います。
shared_ptr<classB> a;
if(myapp.advanced == true) a.reset(new class1);
else a.reset(new class2);
a->something();
2)テンプレート関数を書く:
template <typename T> void do_something(T& t)
{
t.something();
}
...
if(myapp.advanced)
{
class1 a;
do_something(a);
}
else
{
class2 a;
do_something(a);
}
class1
とclass2
を変更して基本クラスを追加できない場合、2番目の方法が適していることに注意してください。私はまた、do_something
の中のビットが、問題のオブジェクトのsomething()
を呼び出すより複雑であると仮定しています。そうでなければ、直接呼び出すことができます。
EDIT:もう少し明確にするために、2番目の方法では問題の残りの機能で利用できるようにはなりません。代わりに新しい機能が追加されます。
コーディングロジックは、Class1とClass2に共通することを示しています。共通の基底クラスから派生させることで、これをコードで表現します。 次に、派生クラスのインスタンスを保持するために基本クラスポインタを使用します。
は、このアプローチする多くの方法がありますが、それ以上の情報なしで、私はおそらくあなたがこれを行うにアドバイスします:私はクラスがベースと呼ばれる共通の祖先を持っていると仮定し
をもちろん
Base* a;
if (myapp.advanced == true)
a = new class1();
else
a = new class2();
あなたはいけません必要がなくなった後にスマートポインタを使用してdelete
を発行することを忘れないでください。
このif-elseステートメントを頻繁に繰り返す場合は、このプロシージャを何らかの関数またはファクトリ・クラスでラップするほうが良いかもしれませんが、状況は状況によって異なります。
elseブランチには 'a = new class2;'を意味します:) –
はい、もちろん、ありがとう) – Palmik
は 'mの値ですyapp.advanced'はコンパイル時に知られていますか? –
@Steve:いいえ、プログラムの実行時にユーザーによって設定されます。 – thorvald
'if(myapp.advanced)' –