0

似たような構造のクラスが2つあります。

class A{
    int a;
    char *b;
    float c;
    A(char *str) { //allocate mem and assign to b }
};

class B{
    int a;
    char *b;
    float c;
    B(char *str) { //allocate mem and assign to b }
    B(B & bref) { //properly copies all the data }
};

BのオブジェクトをのオブジェクトにコピーしたいA。次の変換は問題ありませんか?

A aobj("aobjstr");
B bobj("bobjstr");
bobj = aobj;    //case 1
bobj = B(aobj); //case 2

ケース2は機能しますか?Bのコピーコンストラクターが呼び出されたときのaobjように、適切に変換および解釈されますか?B &

編集:どうですか?

B bobj(aobj)
4

3 に答える 3

2

いいえ、変換コンストラクターまたは変換演算子を記述せずに、関連のない型間で暗黙的に変換することはできません。おそらく、コンパイラがこれを教えてくれました。私は次のようなエラーを出しました:

error: no match for ‘operator=’ in ‘bobj = aobj’
note:  no known conversion for argument 1 from ‘A’ to ‘const B&’
error: no matching function for call to ‘B::B(A&)’

B変換コンストラクターを指定することで、変換を許可できます。

class B {
    // ...
    B(A const & a) { /* properly copy the data */ }
};

クラスを変更できない場合は、変換を行うために非メンバー関数が必要になります。ただし、これはおそらくクラス メンバーが public である場合にのみ可能です。あなたの例では、コンストラクターを含むすべてのメンバーがプライベートであるため、クラスはまったく使用できません。おそらく、実際のコードではそうではありません。

どちらも同じデータ メンバーを持つ標準レイアウト型であるため、危険な状態で生きたい場合は、Aオブジェクトを として明示的に再解釈することで回避できる場合があります。B

// DANGER: this will break if the layout of either class changes
bobj = reinterpret_cast<B const &>(a);

クラスはメモリを割り当てるため、デストラクタでメモリの割り当てを解除する必要があることに注意してください。また、二重削除を回避するには、 Rule of Threeに従って、コピー コンストラクターとコピー代入演算子の両方を正しく実装する必要があります。

これらすべてstd::stringが面倒だと思われる場合は、メモリ管理を代行してくれる を使用してみてはいかがでしょうか。

于 2013-02-21T07:30:19.623 に答える
2

コンパイルしようとすると、どれもうまくいかないことがわかります。1 つには、コンストラクターはprivate.

bobj = aobj;    //case 1

これは、シグネチャを使用して代入演算子を呼び出そうとします。

B& B::operator =(A const&)

これは存在しないため、コンパイルは失敗します。

bobj = B(aobj); //case 2

A::operator B()これは存在しないを呼び出そうとし、コンパイルは失敗します。

ついに:

B bobj(aobj)

B::B(A const&)これは、存在しない署名を持つコンストラクターを呼び出そうとし、コンパイルは失敗します。

あなたは言う、

クラス A と B を変更/修正できません。これらは生成されたものです。

次に、ジェネレーターを修正するか、独自のアダプターを作成する必要があります。

于 2013-02-21T07:41:19.367 に答える
0

これは、次の注意事項を考慮して行うことができます。

1) char* b問題を起こす。aobj を bobj にコピーすると、ポインタの値aobj.bがコピーされますbobj.b。これは、両方が同じメモリ位置を参照していることを意味し、次のように 1 つを変更すると、変更aobj.b[0] = 'Z'が発生bobj.bします。

bこれは、ポインタからフラット配列に変更することで解決できます。

//...
char b[MAXLEN];
//...

これに対するより良い解決策は、コンストラクターを定義し (他の型を受け入れる)、少なくともクラス B の代入 (=) 演算子をオーバーロードし、ポインターの代入を処理する (新しいポインターにバッファーを割り当ててコンテンツをコピーする) ことです。

2) 更新:サンプル構文は次のようになります。

   bobj = B(reinterpret_cast<B&> (aobj));

   // or simply:
   bobj = reinterpret_cast<B&> (aobj);

3)これは危険であり、安全ではなく、推奨されないことに注意してください。これは、ソリューションの設計をおそらく変更する必要があることを意味します。たとえば、A と B は両方とも共通の基本クラスから継承する場合があります。B は A から継承します。または B は、クラス A のコンストラクターと代入演算子を明示的に定義します。これらは、はるかに推奨されます。

于 2013-02-21T07:37:51.410 に答える