2013-02-11 102 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

相关问题