1

C++ スライスの問題があります。私はC++を初めて使用するので、これができないことに気付くには愚かすぎるかもしれません....さまざまな回避策を試しましたが、現在の最善のアプローチは次のようになります。(非常に大規模なレガシー コード ベースで大量のインターフェイスを変更することを避けるために、このようなことを行う必要があります。これがエレガントなスタイルであるとは決して主張しません!!)

これをコンパイルするのに問題があります。アイデアは正しいですか?それとも、アプローチ全体が失敗する運命にあるのでしょうか? 参照のコンストラクターが問題のようです。私は Stroustrup の "C++ Programming Lanugage" (または少なくとも関連するセクションだと思っていたもの) を読みましたが、役に立ちませんでした。

class FOO {};

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

class BAR {
public:
    BAR(const FOO foo) : _foo(foo), _realFoo(&_foo) { }

BAR(const FOOSUBCLASS foosc) : _foosc(foosc), _realFoo(&_foosc) {} 
private:
    FOO _foo;
    FOOSUBCLASS _foosc;
    FOO& _realFoo;
};

_realFoo(&_foo)コンパイラは私の行を好きではありません。_fooへの参照を、クラスのメンバー変数からの参照にしたいのですが。それはC++では不可能ですか?

VS2005 からの特定のエラーは次のとおりです。

'initializing' : cannot convert from 'FOO *' to 'FOO &'
4

2 に答える 2

2

_fooですFOO&
&_fooですFOO*
コンパイラcannot convert from 'FOO *' to 'FOO &'
あなたが欲しいのは..., _realFoo(_foo)

無関係: おそらく実際に必要なのはstd::unique_ptr<FOO>メンバーです。これははるかに小さくなり、エラーが発生しにくくなります。

あなたが今持っている構造体には、 の完全で完全なインスタンスFOOと、 の完全で完全なインスタンスFOOSUBCLASS、および参照が含まれています。少なくとも2 つのものを和集合に入れるとFOOのサイズは最大の導関数BARよりもわずかに大きくなります。FOOそれはおそらく.aと同じメモリを使用するでしょうunique_ptr<FOO>. 残念ながら、unions は C および C++ のバグの一般的な原因です。

別の問題は、誰かがやって来て書いた場合です

class FOOSOMETHINGELSE : public FOO {
   int buffer[1024];
};

次に、クラスを見つけてBAR変更し、さらに大きくして、BARどこでも使用するすべてのコードを再コンパイルする必要があります。一方、を使用した場合は、何もunique_ptr<FOO>変更BARまたは再コンパイルする必要はありません。エラーの可能性が低くなります。

于 2012-10-11T23:57:22.873 に答える
1

ここにはいくつかの問題があります。それらの1つをスライシングとして正しく識別しますが、スライシングはコンパイル時のエラーを引き起こしません(これが非常に恐ろしいことです...)。Mooing Duck の答えは、あなたが抱えているコンパイルの問題を解決するはずですが、スライスの問題は残ります。あなたが持っていると仮定します

FOO *x = new FOOSUBCLASS;
BAR y(*x);

次のコンストラクターが呼び出されるため、これによりスライスが発生します。

BAR(const FOO foo) : _foo(foo), _realFoo(&_foo) { }

つまり、派生からベースへのコピーが発生します。

スライスは、派生クラス タイプのオブジェクトを基本クラス オブジェクトに割り当てようとすると発生します。たとえば、ここで行っているように、基本クラスを値で受け取る関数に派生クラスを渡すことによって発生します。基本的に、派生クラス オブジェクトのすべてのデータ メンバーは、基本クラス オブジェクトを保持するのに十分な大きさのメモリに収まる余地がないため、静かに「切り捨てられます」。実際に派生クラスである可能性があるオブジェクトを操作する必要がある場合は、参照ポインター (または や のようなスマート ポインター) を使用する必要があります。shared_ptrunique_ptr

ここでやりたいことは、オブジェクトがオブジェクトまたはその派生物BARであるオブジェクトを参照できるようにすることだけだと確信しています-正しいですか? その場合 (そしてオブジェクトの寿命がオブジェクトの寿命を超えているFOOと仮定すると)、必要なのは次のとおりです。FOOBAR

class BAR {
public:
    explicit BAR(FOO& foo) : _foo(foo) {}

private:
    FOO& _foo;
};
于 2012-10-12T00:26:27.893 に答える