2

我进行了以下运算符重载测试:

#include <iostream>
#include <string>

using namespace std;

class TestClass
{
    string ClassName;

    public:

    TestClass(string Name)
    {
        ClassName = Name;
        cout << ClassName << " constructed." << endl;
    }

    ~TestClass()
    {
        cout << ClassName << " destructed." << endl;
    }

    void operator=(TestClass Other)
    {
        cout << ClassName << " in operator=" << endl;
        cout << "The address of the other class is " << &Other << "." << endl;
    }
};

int main()
{
    TestClass FirstInstance("FirstInstance");
    TestClass SecondInstance("SecondInstance");

    FirstInstance = SecondInstance;
    SecondInstance = FirstInstance;

    return 0;
}

赋值运算符按预期运行,输出另一个实例的地址。

现在,我将如何从另一个实例中实际分配一些东西?例如,像这样:

void operator=(TestClass Other)
{
    ClassName = Other.ClassName;
}
4

5 回答 5

5

赋值运算符的传统规范形式如下所示:

TestClass& operator=(const TestClass& Other);

(您也不想调用复制构造函数进行赋值)并且它返回对*this.

一个简单的实现会单独分配每个数据成员:

TestClass& operator=(const TestClass& Other)
{
  ClassName = Other.ClassName;
  return *this;
}

(请注意,这正是编译器生成的赋值运算符会做的事情,所以重载它是没有用的。不过,我认为这是为了锻炼。)

更好的方法是使用Copy-And-Swap idiom。(如果您发现 GMan 的答案太压倒性,请尝试的,这不太详尽。:))请注意,C&S 使用复制构造函数和析构函数来进行赋值,因此需要每个副本传递对象,就像您在问题中所说的那样:

TestClass& operator=(TestClass Other)
于 2010-12-22T13:46:56.747 回答
5

您显示的代码可以做到这一点。但是,没有人会认为这是一个特别好的实现。

这符合赋值运算符的预期:

TestClass& operator=(TestClass other)
{
    using std::swap;
    swap(ClassName, other.ClassName);
    // repeat for other member variables;
    return *this;
}

顺便说一句,您谈论“其他类”,但您只有一个类,以及该类的多个实例。

于 2010-12-22T13:49:02.047 回答
3

几乎都说了,几点说明:

于 2010-12-22T13:50:21.923 回答
1

传统上,赋值运算符和复制构造函数是通过 const 引用定义的,而不是使用按值复制的机制。

class TestClass 
{
public:
    //... 
    TestClass& operator=(const TestClass& Other)
    {
        m_ClassName= Other.m_ClassName;
        return *this;
    }
private:
    std::string m_ClassName;
 }

编辑:我更正了,因为我放置了没有返回 TestClass& 的代码(参见 @sbi 的答案)

于 2010-12-22T13:46:25.867 回答
0

您对如何从其他类复制内容是正确的。简单的对象只能使用operator=.

但是,请注意TestClass包含指针成员的情况——如果您只是使用 分配指针operator=,那么两个对象都会有指向同一内存的指针,这可能不是您想要的。相反,您可能需要确保分配一些新内存并将指向的数据复制到其中,以便两个对象都有自己的数据副本。请记住,在为复制的数据分配新块之前,您还需要正确释放已分配对象已指向的内存。

顺便说一句,您可能应该这样声明operator=

TestClass & operator=(const TestClass & Other)
{
    ClassName = Other.ClassName;
    return *this;
}

这是重载时使用的一般约定operator=。return 语句允许链接赋值(如a = b = c)并通过const引用传递参数避免Other在其进入函数调用的过程中复制。

于 2010-12-22T13:46:23.107 回答