问题描述
我正在学习C ++,我对赋值运算符有疑问。
根据此处https://en.cppreference.com/w/cpp/language/copy_assignment的内容,
...一个类可以具有多个副本分配运算符,例如都T& T :: operator =(const T&)和T&T :: operator =(T)。
我试图同时使用两个运算符创建一个类,但我看不出哪里出了问题,因为我是从编译器得到的:
错误C2593:“运算符=”不明确*
这是课程:
class Point2D
{
public:
Point2D(); // default constructor
Point2D(double xValue,double yValue); // overloaded constructor
Point2D(const Point2D& ref); // copy constructor const
Point2D(Point2D& ref); // copy constructor for copy and swap
Point2D(Point2D&& moveRef); // move constructor
~Point2D(); // destructor
Point2D& operator=( const Point2D& other ); // copy assignment operator const
Point2D& operator=( Point2D other ); // copy assignment operator for copyAndSwap
private:
double x;
double y;
int *ptr;
};
这是给我错误的地方:
void copy_assign_test()
{
cout << endl << "copy assign" << endl;
Point2D a(1,1);
Point2D b(2,2);
Point2D c(3,3);
Point2D& ptRef = c;
Point2D d(6,6);
a = ptRef; // error: ambiguous operator
b = a; // // error: ambiguous operator
d = Point2D(7,7); // error: ambiguous operator
}
我的问题涉及以下方面:
- 如果
a=ptRef
是引用,为什么ptRef
含糊? - 如果未将
b=a
声明为引用,为什么a
不明确? - 如果
d = Point2D(7,7)
不是参考,为什么Point2D(7,7)
模棱两可?
我使用Visual Studio 2019和C ++ 17标准编译的所有测试。
解决方法
您引用的文档来自C ++标准的[class.copy]
(C ++ 14)/ [class.copy.assign]
(C++17)部分:
15.8.2复制/移动分配运算符
- 用户声明的副本分配运算符X :: operator =是非静态的 具有 的X的非模板成员函数恰好是 类型X,X&,const X& ,volatile X&或const volatile X&。 121 [注意: 重载的赋值运算符必须声明为只有一个 参数;参见16.5.3.-尾注] [注:不止一种复制形式 可以为一个类声明赋值运算符。—尾注]
(添加了重点)
因此,您引用的文档是正确的,尽管它引用了标准中的 Note 。 [编辑:截图]
如果标准允许,为什么不编译?
在说明了允许哪些参数以及允许重载之后,该标准也不必说明哪些组合有效(无效),因为这将意味着重复自身。冗长的[over.match]
第16.3节及其20页概述了超载解决方案规定(以及由此带来的歧义和冲突规则)。
a = ptRef;
是很大的函数调用,因为ptRef
可以由ref或value传递给const arg或不传递给const arg。
在您所有的情况下,分配都匹配两种模式。
无论如何,我不明白为什么在实施 Point2D& operator=( Point2D other );
时需要使用Point2D& operator=( const Point2D& other );
运算符。