2013-02-11 93 views
0

我使用base-from-member成語,我現在堅持與他們複製/移動構造函數。假設下面的代碼:這裏複製/移動構造函數的基礎成員成語

#include <iostream> 
#include <string> 
#include <boost/lexical_cast.hpp> 

using namespace std; 

struct A // base class 
{ 
    A(string &s) : s(s), c(0) { }; 
    A(const A &a) : s(a.s), c(a.c) { }; 
    void print() { cout << s << endl; c++; } 
    int print_count() { return c; } 

    string &s; 
    int c; 
}; 

struct B_base // this class will be initialized before A 
{ 
    B_base(int i) 
    { 
     s = boost::lexical_cast<string>(i); 
    } 

    B_base(const B_base &other) : s(other.s) { }; 

    string s; 
}; 

struct B : B_base, A // main class 
{ 
    B(int i) : B_base(i), A(B_base::s) { } 
    B(const B &other) : B_base(other), A(other) { } // <-- problem here 

    using A::print; 
    using A::print_count; 
}; 


int main() 
{ 
    B b(10); 
    b.print(); // prints '10' 
    cout << b.print_count() << endl; // prints '1' 


    B b1(b); 
    b1.print(); // prints '10' 

    A &a = b; 
    a.s = "FAIL"; // we modify b, not b1 here! 

    b1.print(); // but b1 prints 'FAIL' here --- error (it should still print '10') 
    cout << b.print_count() << " " << b1.print_count() << endl; // prints '1 3' 

    return 0; 
} 

問題是,參考A.s(其是指向B_base::s)被複制從一個實例到另一個,而應該被修改爲指向另一個B_base::s。如果先前的實例超出了以懸空引用結尾的範圍,情況可能更糟。

我的問題是:如何使用基於成員的成語製作正確的副本? (我認爲移動構造函數將類似於複製一個,對不對?)

+0

A(const的A&A):S(A.S),...其中弦&S不是const的?你可以修改一個使用s。 – qPCR4vir 2013-02-11 18:31:51

回答

0

你在這種情況下,正在行使的基礎,從成員成語的意思是:你想class BA導出與已經使用的成員初始化B(帶有:string s)。

B b(10); 
B b1(b); // B(const B &other) : B_base(other), A(other) { } 
     // now A::s in b1 is a ref to b.s 
A &a = b;// and a.s is a ref to b.s too. 
a.s = "FAIL"; // we modify b, and A::s in b1 to! 

這個問題是可以解決的製作拷貝構造函數:

B(const B &other) : B_base(other), A(B_base::s) { } 

另外,具有A::sB_base::s具有相同的名稱,使事情更加難以理解。

編輯:作爲類設計師,你必須決定是你的複製構造函數的確切含義。
例如,在這種情況下,您可能需要跟蹤每個新創建對象A的打印數量(使用A::c)。我建議的複製構造函數是這樣做的。

但是如果你想跟蹤所有原始字符串的打印事情是比較複雜的。只需注意,如果將舊的A::c複製到新的A,它將被正確初始化,當使用A的不同副本打印相同的原始字符串時,不會實現交叉驗證。如果這不是一個問題,你可以修改構造函數:

A(string &s, int _c=0) : s(s), c(_c) { }; 

...

B(const B &other) : B_base(other), A(B_base::s, other.c) { } 
+0

但是'A'的狀態會發生什麼(例如'c')?我想複製它(更一般地說:'A'的內部狀態)。 – 2013-02-11 23:43:42

+0

@討厭引擎。這是你作爲班級設計師的決定。在編輯中查看我的意見: – qPCR4vir 2013-02-13 08:04:07

相關問題