私は典型的なダイヤモンドの問題のように仮想継承を使用しています:仮想基本クラスの代入演算子が1回だけ呼び出されるようにするにはどうすればよいですか?
A
(virtual)/ \ (virtual)
B C
\ /
D
私はすべてのクラスで「deep_copy_from」という名前のメソッドを実装しています(しかし、それは同様=()代入演算子することができます)。メソッドは、クラス自身の属性をコピーし、そのコピーを上記のクラスに伝播する必要があります。
問題は、Dインスタンスを深くコピーしているときにA :: deep_copy_fromメソッドが2回呼び出されてしまうことです(Aの「バージョン」が1つしかないため、一度呼び出す必要があります)。一度しか呼び出されないようにするにはどうすればよいでしょうか?
(B :: deep_copy_fromとC :: deep_copy_fromは同じように動作する必要があります)。ここ
は、サンプルコードである:ここ
class A
{
public:
A(string const& p_a_name) : a_name(p_a_name) {
cout << "A(a_name=\"" << p_a_name << "\")" << endl;
}
virtual void deep_copy_from(A const& a)
{
cout << "A::deep_copy_from(A(a_name=\"" << a.a_name << "\"))" << endl;
this->a_name = a.a_name;
}
protected:
string a_name;
};
class B : public virtual A
{
public:
B(string const &p_a_name, string const& p_b_name) : A(p_a_name), b_name(p_b_name) {
cout << "B(a_name=\"" << p_a_name << "\", b_name=\"" << p_b_name << "\")" << endl;
}
virtual void deep_copy_from(B const& b)
{
cout << "B::deep_copy_from(B(a_name=\"" << b.a_name << "\", b_name=\"" << b.b_name << "\"))" << endl;
this->A::deep_copy_from(static_cast<A const&>(b));
this->b_name = b.b_name;
}
protected:
string b_name;
};
class C : public virtual A
{
public:
C(string const &p_a_name, string const& p_c_name) : A(p_a_name), c_name(p_c_name) {
cout << "C(a_name=\"" << p_a_name << "\", c_name=\"" << p_c_name << "\")" << endl;
}
virtual void deep_copy_from(C const& c)
{
cout << "C::deep_copy_from(C(a_name=\"" << c.a_name << "\", c_name=\"" << c.c_name << "\"))" << endl;
this->A::deep_copy_from(static_cast<A const&>(c));
this->c_name = c.c_name;
}
protected:
string c_name;
};
class D : public B, public C
{
public:
D(string const &p_a_name, string const& p_b_name, string const& p_c_name, string const& p_d_name)
: A(p_a_name), B(p_a_name, p_b_name), C(p_a_name, p_c_name), d_name(p_d_name)
{
cout << "D(a_name=\"" << p_a_name << "\", b_name=\"" << p_b_name
<< "\", c_name=\"" << p_c_name << "\", d_name=\"" << p_d_name << "\")" << endl;
}
virtual void deep_copy_from(D const& d)
{
cout << "D::deep_copy_from(D(a_name=\"" << d.a_name << "\", b_name=\"" << d.b_name
<< "\", c_name=\"" << d.c_name << "\", d_name=\"" << d.d_name << "\"))" << endl;
this->B::deep_copy_from(static_cast<B const&>(d));
this->C::deep_copy_from(static_cast<C const&>(d));
this->d_name = d.d_name;
}
protected:
string d_name;
};
電流出力である:
A(a_name="A")
B(a_name="A", b_name="B")
C(a_name="A", c_name="C")
D(a_name="A", b_name="B", c_name="C", d_name="D")
D::deep_copy_from(D(a_name="A", b_name="B", c_name="C", d_name="D"))
B::deep_copy_from(B(a_name="A", b_name="B"))
A::deep_copy_from(A(a_name="A"))
C::deep_copy_from(C(a_name="A", c_name="C"))
A::deep_copy_from(A(a_name="A"))
更新:
現在のバージョンは、次のようになる:
class A
{
public:
A(string const& p_a_name) : a_name(p_a_name) {
cout << "A(a_name=\"" << p_a_name << "\")" << endl;
}
virtual void deep_copy_from(A const& a)
{
cout << "A::deep_copy_from(A(a_name=\"" << a.a_name << "\"))" << endl;
this->a_name = a.a_name;
}
protected:
string a_name;
};
class B : public virtual A
{
public:
B(string const &p_a_name, string const& p_b_name) : A(p_a_name), b_name(p_b_name) {
cout << "B(a_name=\"" << p_a_name << "\", b_name=\"" << p_b_name << "\")" << endl;
}
virtual void deep_copy_from(B const& b)
{
cout << "B::deep_copy_from(B(a_name=\"" << b.a_name << "\", b_name=\"" << b.b_name << "\"))" << endl;
this->A::deep_copy_from(static_cast<A const&>(b));
this->deep_copy_my_bits_from(b);
}
protected:
void deep_copy_my_bits_from(B const& b) {
cout << "B::deep_copy_my_bits_from(B(a_name=\"" << b.a_name << "\", b_name=\"" << b.b_name << "\"))" << endl;
this->b_name = b.b_name;
}
protected:
string b_name;
};
class C : public virtual A
{
public:
C(string const &p_a_name, string const& p_c_name) : A(p_a_name), c_name(p_c_name) {
cout << "C(a_name=\"" << p_a_name << "\", c_name=\"" << p_c_name << "\")" << endl;
}
virtual void deep_copy_from(C const& c)
{
cout << "C::deep_copy_from(C(a_name=\"" << c.a_name << "\", c_name=\"" << c.c_name << "\"))" << endl;
this->A::deep_copy_from(static_cast<A const&>(c));
this->deep_copy_my_bits_from(c);
}
protected:
void deep_copy_my_bits_from(C const& c) {
cout << "C::deep_copy_my_bits_from(C(a_name=\"" << c.a_name << "\", c_name=\"" << c.c_name << "\"))" << endl;
this->c_name = c.c_name;
}
protected:
string c_name;
};
class D : public B, public C
{
public:
D(string const &p_a_name, string const& p_b_name, string const& p_c_name, string const& p_d_name)
: A(p_a_name), B(p_a_name, p_b_name), C(p_a_name, p_c_name), d_name(p_d_name)
{
cout << "D(a_name=\"" << p_a_name << "\", b_name=\"" << p_b_name
<< "\", c_name=\"" << p_c_name << "\", d_name=\"" << p_d_name << "\")" << endl;
}
virtual void deep_copy_from(D const& d)
{
cout << "D::deep_copy_from(D(a_name=\"" << d.a_name << "\", b_name=\"" << d.b_name
<< "\", c_name=\"" << d.c_name << "\", d_name=\"" << d.d_name << "\"))" << endl;
this->A::deep_copy_from(static_cast<A const&>(d));
this->B::deep_copy_my_bits_from(static_cast<B const&>(d));
this->C::deep_copy_my_bits_from(static_cast<C const&>(d));
this->d_name = d.d_name;
}
protected:
string d_name;
};
そして、出力は次のようになります。
A(a_name="A")
B(a_name="A", b_name="B")
C(a_name="A", c_name="C")
D(a_name="A", b_name="B", c_name="C", d_name="D")
D::deep_copy_from(D(a_name="A", b_name="B", c_name="C", d_name="D"))
A::deep_copy_from(A(a_name="A"))
B::deep_copy_my_bits_from(B(a_name="A", b_name="B"))
C::deep_copy_my_bits_from(C(a_name="A", c_name="C"))
私はそれよりももっと良いものを得ることができますか? (より自動)
これまではこれまでやったことはありませんが、BとCで 'deep_copy_from'を呼び出すのではなく、A、B、Cで' deep_copy_just_my_bit'を呼び出すことができました。言語は、例えば、Aのコンストラクタ/デストラクタはDにアクセス可能である必要がありますが、非仮想ベースのコン/デストラクタは直接の派生クラスからアクセス可能である必要があります。工事はあなたがここで望むように、同じクラスのプロパティごとに同じことをします。言語が特別なルールなしに問題を解決できない場合、私はどちらかといえます。 –
このように継承を使用する必要がありますか? 「is a」から「a have」までの関係の少なくとも一部を改造することは貴重な時間かもしれません。 – Patrick
@スティーブ、コメントではなく答えとして答えたら、あなたは受け入れられるでしょう;) –