我正在研究在C中转换构造函数和转换运算符 . 到目前为止我学到的是,任何只带一个参数(以及任意数量的可选默认参数)的非显式构造函数表示对THAT类类型的隐式类类型转换,例如,如果类定义了一个构造函数,一个 int
类型的参数我可以在需要该类类型的对象的地方使用 int
:
(假设class_type有一个重载的=运算符)
class_type a;
a+=5;
在这种情况下,5被隐式转换(通过转换构造函数)到 class_type
,并调用重载的运算符 .
现在,(至少对我来说)棘手的部分:我知道我可以将转换运算符定义为成员函数:
operator int() {....};
将 class_type
的对象转换为原始 int
类型,我可以使用该转换,如:
class_type a;
a+5;
在这种情况下,我已经读过对象通过其转换运算符转换为int,然后调用内置和运算符 . 但是如果我定义了一个重载运算符来将两个class_type对象作为其参数呢?就像是
class_type operator+(const class_type&,const class_type &c);
编译器如何知道通过函数匹配调用哪一个?转换为 int
只会在仅定义内置运算符时隐式发生?
谢谢!
编辑:
实际上,我已经尝试编写一些代码来有效地尝试它,结果发现我的编译器(g)没有发出任何模糊的调用错误!
这是类头(以及非memeber操作符函数声明):
#include <iostream>
class wrapper {
friend std::ostream &operator<<(std::ostream&,const wrapper&);
public:
wrapper()=default;
wrapper(int);
int get();
operator int() const;
wrapper operator+(int);
private:
int a=10;
};
std::ostream &operator<<(std::ostream&,const wrapper&);
这是主要代码:
#include "wrapper.h"
int main()
{
using namespace std;
wrapper w1;
wrapper w2(5);
cout<<w1<<" "<<w2<<endl;
w1+1;
}
现在,我已经定义了从 int
到 wrapper
的转换构造函数和从类类型到 int
的转换运算符(我还重载了<< output运算符以便打印一些结果),但是当编译器计算表达式 w1+1
时似乎很好 . 怎么可能?
2 回答
如果您有以下类声明,其中包含转换构造函数和转换运算符
声明
其中a1和a2被声明为例如
因为不需要调用转换函数,所以格式正确 . 两个操作数都匹配运算符的参数声明 .
但是,如果你要写的话
当编译器发出错误时,因为存在歧义 . 编译器可以应用转换构造函数
A( int )
将第二个操作数转换为类型A
,并调用为A
类型的对象定义的运算符 . 或者它可以应用转换运算符operator int
将第一个操作数转换为类型int
,并为int
类型的对象调用内置operator +
.为避免这种歧义,您可以使用函数说明符
explicit
声明构造函数或运算符(或两者) .例如
要么
在这种情况下,只存在一个隐式转换,并且没有任何限制 .
我想附加上面的描述,有时一些转换运算符可以隐式调用,即使它们是用函数说明符
explicit
声明的 .例如根据C标准(6.4选择声明)
和(5.16条件运算符)
因此,例如,如果上面的类具有使用函数说明符
explicit
声明的以下转换运算符然而,它将被隐含地称为例如以下声明中
这里a将在条件运算符中转换为bool类型的对象 .
编辑:更新您的问题后,这个表达式
与操作员完全匹配
无需转换 . 所以代码编译成功 .
您可以轻松尝试查看编译器的功能:
GCC
编译器会看到两个候选项:
operator+(int, int) <built-in>
和ABC operator+(const ABC&, const ABC&)
. 这意味着它不仅可以隐式地将a + 5
中的5
转换为a
而且将a
隐式转换为int
. 发布这些转换后,operator+
函数都会成为潜在的匹配项 .因此不知道错误 .
是的,否则它不会自动将
class_type
转换为int
. 但是,int
到class_type
会隐式发生,除非你做class_type
的构造函数explicit
:如果您可以访问C 11,那么您还可以明确转换函数: