2016-04-07 33 views
5

我有2個班級,AB。在A我有3個私人領域。在類B中,我想寫一個拷貝構造函數,並初始化類A的私有字段。然而,這不起作用:繼承和複製構造函數 - 如何從基類初始化私有字段?

#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; 
} 

我明白,當我從privateprotected改變它應該工作(和作品,當然) - 但是如何處理,我在我的代碼的情況呢?問題是:如何在複製構造函數中初始化基類中的私有字段?我收到以下錯誤與當前代碼:

/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

所有你需要做的是調用A拷貝構造函數,當您複製構造B

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

由於B繼承A這是法律和A將複製的otherA部分。

還要注意,所有這些指針都是不必要的,使代碼更復雜。我們可以把它想:

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'如何知道應該複製'other'的哪個'部分'?這是因爲我在'A'中有一個拷貝構造函數? – yak

+0

@yak這和[對象切片](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()方法做到這一點。