3

私が扱っている巨大な C++ コード ベースがあります。

新しいサブクラスを導入して、さまざまなコンテキストで使用したいのですが、Java で訓練された私の心は C++ でこれに問題を抱えています。

コードの変更を最小限に抑えたい。したがって、関心のあるメイン クラス (BAR以下) には、 class のメンバー変数がありますFOOFOOというサブクラスを作りたいFOOSUBCLASSです。Java では、これは些細なことです。デフォルトでは、オブジェクトは参照によって保存されます。このコードは (以下に示すように) インターフェイスを変更せずに (参照を導入せずに) このコードを操作しても、アプリケーションを機能させることができますか?

class FOO {
};

class FOOSUBCLASS : FOO {
public:
    FOOSUBCLASS(const int id) {_id = id;}
private:
    int _id;
};

class BAR {
public:
    BAR(const FOO foo) { _foo = foo;}
private:
    FOO _foo;
};

以下は私のメインです:

FOOSUBCLASS fsc(1);
BAR b(fsc);

しかし、これは VS2005 ではコンパイルできません。それは言います:

'type cast' : 'FOOSUBCLASS *' から 'const FOO &' への変換は存在しますが、アクセスできません

明らかな他のコンストラクターを追加すると、同じコンパイラエラーが発生しますBAR

BAR(const FOOSUBCLASS foo) { _foo = foo;}

FOOSUBCLASSC++ についての私の理解は、データを class のオブジェクトにコピーすることFOOです。(代入演算子、またはそのクラスオーバーライドバージョンを使用)しかし、私の場合、追加のメンバー変数FOOSUBCLASS(およびいくつかのオーバーライドされたメンバー関数)があるので、それをしたくありません。メンバー変数が、一部のコンテキストや他のコンテキストで_foo真の型であることを望みます。これは可能ですか?FOOSUBCLASSFOO

ご意見ありがとうございます。

4

4 に答える 4

2

基底クラスを公開する

class FOOSUBCLASS : public FOO {
public:
    FOOSUBCLASS(const int id) {_id = id;}
private:
    int _id;
};

また、BARコンストラクターでのスライスに注意してください

それを避けるためにポインタ/参照に割り当てます:

class FOO
{
};

class FOOSUBCLASS : public FOO
{
public:
    FOOSUBCLASS(const int id) : _id(id) {}
private:
    int _id;
};

class BAR
{
public:
    BAR(const FOO& foo) : _foo(foo)
    {
    }
private:
    FOO& _foo;
};

注: コンストラクター本体で代入の代わりに初期化リスト構文を使用しました。

于 2012-10-11T23:15:31.177 に答える
2

あなたが今書いたようにそれをすることはできません、ごめんなさい。これは「スライシング」と呼ばれ、詳細については、オブジェクトのスライシングとは?

メンバーをポリモーフィックにしたい_foo場合は、ポインターまたは参照を使用する必要があります。もちろん、このようなことを行うときは、生涯管理を意識してください。

于 2012-10-11T23:17:58.047 に答える
1

最初に C++ クラスでは、デフォルトprivateで基本クラスから継承するために使用されます。これはFOOSUBCLASSFOO変換が内部で行われ、アクセスできないことを意味します。したがって、最初に変換class FOOSUBCLASS : FOOclass FOOSUBCLASS : public FOO、2番目はJavaにあり、これはすべて参照であるため、次のように言うことができます

FOOSUBCLASS fs;
FOO f = fs;

ただし、C++ には参照と非参照FOO fがあり、実際にはオブジェクトである非参照を作成するため、一部をコピーFOO f = fsするだけでa への参照が発生せず、これを達成するには、ポインター、参照、またはスマート ポインターを使用する必要があります。たとえば、次のように言えます。FOOfsfFOOFOOSUBCLASS

FOOSUBCLASS* fs = new FOOSUBCLASS;
FOO* f = fs;   // Use pointer is OK
FOO& rf = fs;  // A reference of fs as a FOO
std::auto_ptr<FOO> spf( fs );  // OK, but for this destructor must be virtual
于 2012-10-11T23:31:44.450 に答える
0

ユーザー sehe に加えて、値渡しではなく参照を BAR のコンストラクターに渡すことを検討してください。

class BAR { public: BAR(const FOO& foo) { _foo = foo;} private: const FOO& _foo; };

于 2012-10-11T23:26:50.403 に答える