2016-04-07 10 views
5

私は2つのクラス、ABを持っています。 Aには3つのプライベートフィールドがあります。クラスBでコピーコンストラクタを作成し、クラスAのプライベートフィールドを初期化したいと思います。私はprotectedからprivateから変更したときにそれが仕事(もちろん、作品)必要があることを理解しています継承とコピーコンストラクタ - 基本クラスからプライベートフィールドを初期化する方法?

#include <iostream> 
#include <string> 
using namespace std; 

class A 
{ 
    private: 

     string *field1; 
     string *field2; 
     string *field3; 
     double num1; 

    public: 

     A(string *o, string *n, string *m, double a=0) 
     { 
      field1 = new string(*o); 
      field2 = new string(*n); 
      field3 = new string(*m); 
      num1 = a; 
     } 

     A(const A& other) { 
      field1 = new string(*other.field1); 
      field2 = new string(*other.field2); 
      field3 = new string(*other.field3); 
      num1 = other.num1; 
     } 

     void show() 
     { 
      cout << *field1 << " " << *field2 << " " << *field3 << "\n"; 
     } 

     ~A() 
     { 
      delete field1; 
      delete field2; 
      delete field3; 
     } 
}; 

/*--------------------------------------------------------------------------------------------*/ 

class B : public A 
{ 
    private : 

     double num2; 
     double num3; 

    public: 

     B(double num2, double num3, string *o, string *n, string *num, double a=0) : A(o,n,num,a) 
     { 
      this->num2 = num2; 
      this->num3 = num3; 
     } 

     B(const B& other) : A(other.field1, other.field2, other.field3, other.num1) 
     { 
      num2 = other.num2; 
      num3 = other.num3; 
     } 

     void show() 
     { 
      cout << num2 << " " << num3 << "\n"; 
      A::show(); 
     } 
}; 

int main() 
{ 
    string o = "TEXT 111"; 
    string *optr = &o; 

    string n = "TEXT 222"; 
    string *nptr = &n; 

    string *numptr = new string("9845947598375923843"); 

    A ba1(optr, nptr, numptr, 1000); 
    ba1.show(); 

    A ba2(ba1); 
    ba2.show(); 

    A ba3 = ba2; 
    ba3.show(); 

    B vip1(20, 1000, optr, nptr, numptr, 3000); 
    vip1.show(); 

    B vip2(vip1); 
    vip2.show(); 

    delete numptr; 
    return 0; 
} 

を - しかし、どのように私は私のコードを持っているような状況に対処するために:しかし、これは動作しませんか?問題は、コピーコンストラクタで、基本クラスのプライベートフィールドを初期化する方法ですか?

/home/yak/test.cpp|9|error: ‘std::string* A::field1’ is private| 
/home/yak/test.cpp|61|error: within this context| 
/home/yak/test.cpp|10|error: ‘std::string* A::field2’ is private| 
/home/yak/test.cpp|61|error: within this context| 
/home/yak/test.cpp|11|error: ‘std::string* A::field3’ is private| 
/home/yak/test.cpp|61|error: within this context| 
/home/yak/test.cpp|12|error: ‘double A::num1’ is private| 
/home/yak/test.cpp|61|error: within this context| 
||=== Build failed: 8 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===| 
+1

あなたが示唆したようにそれらを「保護」してから、Bの本体からアクセスします。それらを「保護」することの問題は何ですか? – RJFalconer

+0

'A'を変更できない場合は、あなたが求めていることは不可能です。コードが漏洩しており、例外的な安全性もありません。なぜ文字列へのポインタを使用するのですか? –

+0

@RJFalconer:私は好奇心が強いです。子クラスから 'private'フィールドを初期化する必要があります。私たちが見るように、初期化リストでは動作しません。 – yak

答えて

6

あなたがする必要があるすべては、あなたが、これは合法であるとAotherA一部をコピーしますAからB継承しているのでB

よう
B(const B& other) : A(other) 
{ 
    num2 = other.num2; 
    num3 = other.num3; 
} 

を構築コピーするときAのコピーコンストラクタを呼び出すことです。

これらのポインタはすべて不要であり、コードが複雑になります。我々はそれが好き書き直すことができます:

class A 
{ 
private: 
    string field1; 
    string field2; 
    string field3; 
    double num1; 

public: 
    A(const string& o, const string& n, const string& m, double a = 0) : field1(o), field2(n), feild3(m), num1(a) {} 

    A(const A& other) field1(other.field1), field2(other.field2), feild3(other.feild3), num1(other.num1) {} 

    void show() 
    { 
     cout << field1 << " " << field2 << " " << field3 << "\n"; 
    } 
}; 

/*--------------------------------------------------------------------------------------------*/ 

class B : public A 
{ 
private: 

    double num2; 
    double num3; 

public: 

    B(double num2, double num3, const string& o, const string& n, const string& m, double a = 0) : A(o, n, num, a), num2(num2), num3(num3) {} 

    B(const B& other) : A(other), num2(other.num2), num3(other.num3) {} 

    void show() 
    { 
     cout << num2 << " " << num3 << "\n"; 
     A::show(); 
    } 
}; 
+0

「A」はコピーするべき「その他」の「一部」をどのように知っていますか?それは 'A 'にコピーコンストラクタがあるからです。 – yak

+0

@yak Thatと[object slicing](http://stackoverflow.com/questions/274626/what-is-object-slicing)(ここでは問題ありません)。 – LogicStuff

+0

@LogicStuff:ありがとうございます。 – yak

0

コピーコンストラクタから親コピーコンストラクタを呼び出して、同じ引数を与える必要があります。

1

クラスBのためのコピーコンストラクタを使用して、あなたは、

だから、クラスAのコピーコンストラクタを呼び出して、このいずれかで、あなたのコードに置き換えてください:

B(const B& other) : A(other) 
    { 
     num2 = other.num2; 
     num3 = other.num3; 
    } 

また、クラスAのデストラクタを仮想として宣言します。そして、私はあなたもshow()メソッドのためにそれをしたいと思います。

関連する問題