大家好我在C ++工作了大约一个月,所以如果这个问题太过琐碎,请原谅。
#include <iostream>
using namespace std;
class Point {
int x,y;
public:
Point(int x_val = 0,int y_val = 0) :x(x_val),y(y_val) { }
Point(Point& copy) : x(copy.x), y(copy.y) { }
void showLocation() const { cout << "[" << x << "," << y << "]" << endl; }
friend Point operator+(const Point& p1, const Point& p2);
friend Point operator-(const Point& p1, const Point& p2);
Point operator-(Point& p2) { // (1)
Point(x-p2.x, y-p2.y).showLocation();
return Point(x-p2.x, y-p2.y);
}
};
Point operator+(const Point& p1, const Point& p2) { // (2)
Point pos(p1.x+p2.x, p1.y+p2.y);
return pos;
}
Point operator-(const Point& p1, const Point& p2) { // (3)
return Point(p1.x-p2.x, p1.y-p2.y);
}
int main() {
Point p1(3,4);
Point p2(2,5);
(p1+p2).showLocation();
//(p1-p2).showLocation();
operator-(p1,p2);
}
所以这是一个用于练习运算符重载的简单代码 - 我只是创建了一个点并重载了+和 - 运算符,它们都是类的成员和全局函数。
然而,当我编译这段代码时,我发现虽然(2)有效,但(1)和(3)都会继续显示我无法理解的错误:
q1.cpp:17:10:错误:没有用于初始化的匹配构造函数 &#39;点&#39; 返回点(x-p2.x,y-p2.y); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 注意:候选构造函数不可行:没有已知的转换来自&#39; Point&#39;到&#39; int&#39;第一个参数
据我所知,(1)和(3)都应该返回一个临时的Point对象,根据谷歌的搜索,它应该等同于case(2)。
此外,错误陈述使我更加困惑 - 我无法看到在提到的表达式中发生任何转换是有问题的。
Point(x-p2.x, y-p2.y).showLocation();
这很好用,情况(2)也可以,所以我想这不是语法问题。除了关于返回临时对象(没有命名)的问题的可能性之外,我无法看到任何问题。
谢谢!
答案 0 :(得分:1)
您只需删除复制构造函数即可解决此问题。它没有任何用处。或者,您可以根据默认签名在签名中使用func setupActivityView() {
let screen = UIScreen.mainScreen().bounds
let view = UIView(frame: CGRectMake(0.0, self.navbar.frame.height, screen.width, UIScreen.mainScreen().bounds.height-self.navbar.frame.height))
view.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.80)
//view.hidden = true
self.activityView = view
self.view.addSubview(view)
let spinner = UIActivityIndicatorView(activityIndicatorStyle: .WhiteLarge)
spinner.startAnimating()
spinner.hidesWhenStopped = true
self.spinner = spinner
/*POINT:1*/ spinner.center = view.center
/*POINT:2*/ spinner.frame.size = CGSizeMake(37.0, 37.0)
/*POINT:3*/ //spinner.frame = CGRectMake((view.frame.width/2) - 18.5, (view.frame.height/2) - 18.5, 37.0, 37.0)
view.addSubview(spinner)
}
来修复复制构造函数。
const
如果没有Point(Point const & copy) : x(copy.x), y(copy.y) { }
,则复制构造函数不能与临时实例一起用作输入。
资源:
答案 1 :(得分:0)
此:
Point(Point& copy) : x(copy.x), y(copy.y) { }
是技术上有效的复制构造函数,但它限制了可能的实际参数。
临时或const
对象不能绑定到Point&
形式参数,因为这是对非const
的引用,这将允许修改实际参数。
相反,你可以写
Point( Point const& other ): x( other.x ), y( other.y ) {}
我还纠正了误导性的争论命名。
但是更容易,对于这门课你可以做到
Point( Point const& other ) = default;
绝对最简单,只是根本不要定义复制构造函数,让编译器为你做。
同样,为了获得最大的可用性,您应该更改
Point operator-(Point& p2) { // (1)
到
Point operator-(Point const& p2) const { // (1)
参数的const
表示现在可以使用const
或临时(rvalue)参数调用它。
成员函数本身的const
,即最后const
,意味着可以在const
对象上调用它。这里的规则有点微妙。与参数的限制相反,没有const
它就可以在临时对象上调用(即通过rvalue-expression)。
一般建议:
在任何可以使用的地方随意撒上const
让编译器生成复制操作,除非您负责复制,
优先使用复制安全的类型的数据成员,例如内置类型,智能指针和标准库集合。
答案 2 :(得分:0)
错误的原因(在您的情况下为(1))是
Point operator-(Point& p2) { // (1)
Point(x-p2.x, y-p2.y).showLocation();
return Point(x-p2.x, y-p2.y);
}
是Point(x-p2.x, y - p2.y)
生成一个临时对象。返回(语义上)需要创建临时副本,这需要一个接受const
参数的拷贝构造函数。您的复制构造函数不接受const
参数。
解决方案是修改你的拷贝构造函数以接受const
参数,或者完全删除它(因为编译器会自动生成一个适合你的拷贝构造函数)。在C ++ 11中,如果需要,使用Point(const Point &) = default;
来强制编译器生成正确的拷贝构造函数。
注意:该标准要求编译器强制要求正确的复制构造函数,即使临时优化已经存在。这有助于提高代码的可移植性,使编译器不会优化临时性。
您的代码的另一个问题是您有operator-()
的两种变体。
您的案例(1)和(3)不相同。第一个生成operator-()
的成员函数形式(它接受一个参数,因为存在隐含的this
),第二个是非成员形式,它接受两个参数。
当它看到p1-p2
这样的表达式(其中p1
和p2
都属于Point
类型)时,operator-()
的两个版本都同样出色候选人。编译器会抱怨歧义,因为它没有理由偏爱另一个。所以声明
(p1-p2).showLocation();
不会编译。我认为你已经因为这个原因对它进行了评论。
解决方法是使用operator-()
的一种形式或另一种形式。不是一次两个。