C++赋值运算符可以作为自由函数吗?

22

我正在尝试类似这样的东西:

Foo & operator=(Foo & to, const Bar &from);

但是我遇到了这个错误:

E2239 'operator =(Foo &, const Bar &)' must be a member function

有哪些限制条件规定了哪些运算符可以/不可以作为自由函数来定义?如果有,为什么会有这些限制条件?

2个回答

29

赋值运算符必须是非静态成员函数,并且必须只有一个参数:

赋值运算符应由一个非静态成员函数实现,并且只有一个参数(C++03 13.5.3/1)。

operator()operator[]operator-> 必须也被实现为非静态成员函数。

类特定的operator newoperator delete(以及其变体)必须作为静态成员函数实现(请注意,即使没有使用static关键字声明,它们也是隐式静态的)。


3
还有其他原因吗?毕竟,赋值运算符(operator=)是三个(即拷贝构造函数,赋值运算符和析构函数)复制控制函数之一,所以将其作为成员函数是合理的。但是其他函数为什么也要这样呢? - Joey.Z
1
@zoujyjs 运算符必须能够访问内部成员变量(可能是私有的)。自由函数将无法访问这些变量。 - iheanyi
@iheanyi 但是我们可以将自由函数定义为类的友元。 - J.zhou
@A.Joe,你说得对,那不是很清楚。这些运算符通过隐式this指针访问成员变量。自由函数必须被传递一个指向对象的指针或引用。这意味着语言必须有特定的参数顺序来处理这种方法,以便正确地传递对象指针。程序员需要负责正确编写所有组合的const/non-const版本的这些方法。与直接使用语言中已经构建好的成员函数相比,这似乎是一个容易出错的浪费时间。 - iheanyi
这个论点(双关语)也适用于所有需要“正确排序”和完全访问(通过友元)私有成员函数的数学运算符。 - David V. Corbin

-1

它不能。

我猜原因与复制构造函数有关。它们具有非常相似的语义,而且你不能像其他构造函数一样在类外定义复制构造函数。所以,他们不想把这对双胞胎分开太远(以避免双胞胎悖论)。

P.S. 在C++中令人遗憾的是,你不能向现有类添加成员。这没有低级别的原因。如果可能的话,你可以通过不在类定义头文件中声明私有函数来解耦头文件和cpp依赖项。


7
如果你所说的是在类定义完成后添加成员,那么肯定有理由这样做。你不能随意添加虚成员,因为在类定义完成时,编译器必须知道对象(包括vtable)的大小。在类定义之外添加非虚成员会使“private”变得毫无意义,因为任何人都可以添加成员来检查/修改私有数据。在C++整个语境中,这将破坏他们试图实现的很多东西。 - Michael Kohne
首先,添加公共成员可能是一个不错的选择。其次,更重要的是,它只需要在类定义中添加“friend”或某种前向声明,这将有助于解耦依赖关系。 - Pavel Radzivilovsky
我不明白你关于C++中“羞耻感”的观点。如果你真的想要向现有类别中“添加”一些东西,为什么不创建一个子类?相反,如果你打算在完全实现后“修改”原始类别,我认为这不是C++的工作方式。 - Diaz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接