我不明白在这个例子中什么时候调用构造函数
I don't understand when the constructor is called in this example
嗨,我一直在尝试分析以下使用操作重载的代码。
#include <iostream>
using namespace std;
#define DBG(str) cout << str << endl
class Integer {
int n;
public:
Integer(int _n) : n(_n) { DBG("A"); };
Integer(const Integer& i) : n(i.n) { DBG("B"); };
Integer& operator=(const Integer& i) { DBG("C"); n = i.n; return *this; };
Integer& operator+=(const Integer& i) { DBG("D"); n += i.n; return *this; };
friend Integer operator+(const Integer& a, const Integer& b);
friend Integer operator*(const Integer& a, const Integer& b);
friend ostream& operator<<(ostream& os, const Integer& i);
};
Integer operator+(const Integer& a, const Integer& b) {
DBG("E"); return Integer(a.n + b.n);
}
Integer operator*(const Integer& a, const Integer& b) {
DBG("F"); return Integer(a.n * b.n);
}
ostream& operator<<(ostream& os, const Integer& i) {
DBG("G"); os << i.n; return os;
}
int main() {
Integer n1(1), n2(2);
Integer n = 5 + n1 + 2 * n2;
cout << n << endl;
}
结果是...
A // constructor called when n1 is created
A // constructor called when n2 is created
A // when is this called?
A // when is this called?
F // called when 2 * n2 is operated
A // called when Integer(a.n * b.n) is created in the multiplication function
E // called when 5 + n1 is operated
A // called when Integer(a.n + b.n) is created in the addition function
E // called when (5 + n1) + (2 * n2) is operated
A // called when Integer is created in the addition function
G // called when n is printed using cout
5 // value of n
现在我最麻烦的是 A 的第三次和第四次打印。在句子中Integer n = 5 + n1 + 2 * n2;
正在创建对象 n 并将正确的值分配给 n,因此应该调用复制构造函数?我认为应该发生的是应该调用构造函数来制作(5 + n1 + 2 * n2)
的临时对象,然后通过将其复制到 n,应该调用复制构造函数。我理解错了什么?
你能解释一下发生了什么吗?提前谢谢你。
问题出在这一行:
Integer n = 5 + n1 + 2 * n2;
没有int
和Integer
的operator+
,但编译器默默地做了从int
到Integer
的隐式转换,因为默认情况下所有单参数构造函数都可以用作转换方法。 这是您的实时代码(有所改进)。
这是C++的危险特性之一,因此在构造函数之前可以使用explicit
关键字。如果添加它:
explicit Integer(const Integer& i) : n(i.n) { DBG("B"); };
编译器将报告错误,因为现在无法执行隐式转换,并且没有operator+(int, const Integer&)
和operator*(int, const Integer&)
。
您的operator+
和operator*
函数接收const Integer&
作为参数。
当计算此行时(5 + n1 + 2 * n2
)5和2将自动转换为Integer
。
如果不希望转换它们,则应考虑为int
创建运算符作为参数。
编辑:您也可以使用显式构造函数。
例如:explicit Integer(int _n){...}
感谢您的评论@formerlyknownas_463035818
仅当运算符函数的第一个参数不是为其定义运算符函数的目标类的对象时,才在运算符重载中使用 Friend 函数。 在您的情况下,Integer
:
Integer operator+(const Integer& a, const Integer& b) {
DBG("E"); return Integer(a.n + b.n);
}
Integer operator*(const Integer& a, const Integer& b) {
DBG("F"); return Integer(a.n * b.n);
}
,第一个参数确实是Integer
类型的对象,它是您的目标类。您可能希望能够将Integer
对象与基元整数类型一起使用为操作数。 将您的好友函数签名更改为:
Integer operator+(const int& a, const Integer& b) {
DBG("E"); return Integer(a + b.n);
}
Integer operator*(const int& a, const Integer& b) {
DBG("F"); return Integer(a * b.n);
}
请注意,使用a
而不是a.n
,因为当运算符函数定义为友元时,两个操作数都作为参数传递。(与第一个操作数是调用对象的非友元运算符函数不同)。因此,a
包含类型为int
的值,而不是类型Integer
的值。
对包含
DBG("A")
的构造函数的匿名调用是 5 和 2 从int
转换为Integer
时发生的隐式转换的结果。
尽管您的代码可能有效,但这是不可靠的。 希望这有帮助。
- 什么时候调用组成单元对象的析构函数
- 什么时候调用析构函数
- boost odeint什么时候真正调用观测者
- 什么时候可以使用常量装饰调用我的重载函数?
- 什么时候用指针调用C++类构造函数
- 我不明白在这个例子中什么时候调用构造函数
- 调用boost.asio的异步函数时,线程是什么时候创建的
- 什么时候调用CMFCListCtrl::OnGetCellBkColor函数?
- C++什么时候是使用无默认构造函数与getter和setters与直接调用类中的变量的正确时机
- 如果绝对没有调用成员函数,是否允许使用不完整类型的向量?如果是这样,从什么时候开始
- 什么时候调用 glFlush 太频繁了
- C 什么时候被调用
- 被调用的函数究竟什么时候结束
- c++.系统调用move什么时候会失败
- 什么时候应该使用ASM调用
- c++中究竟什么时候调用析构函数?
- 谁能告诉我什么时候调用terminate(),什么时候调用unexpected() ?
- 在常量和非常量引用变量的情况下,什么时候决定调用哪个函数
- c++在什么时候调用类成员对象的构造函数?
- 在什么时候WM_ENDSESSION调用wParam为0