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。如果前一个实例超出范围并以悬空引用结尾,情况可能会更糟。

我的问题是:如何使用 base-from-member 成语制作正确的类副本?(我认为移动构造函数将类似于复制一个,对吧?)

4

1 回答 1

0

在这种情况下,您正在使用的 base-from-member 习语意味着:您希望必须使用(with is: ) 的成员来初始化 with的class B派生。ABstring 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::c)跟踪每个新创建对象的打印次数A。我建议的复制构造函数做到了。

但是如果你想跟踪原始字符串的所有打印,事情就更复杂了。请注意,如果您将旧的复制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) { }
于 2013-02-11T20:23:30.150 回答