我正在研究C ++中的转换构造函数和转换运算符。到目前为止,我了解到的是,仅采用一个参数(以及任意数量的可选默认参数)的任何非显式构造函数都表示将隐式类类型转换为THAT类类型,例如,如果一个类定义了一个具有类型int
I的参数可以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 ++)不会发出任何歧义的调用错误!
这是类标头(以及非成员operator +函数声明):
#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
AND的转换构造函数,从类类型为转换了一个运算符int
(为了显示一些结果,我也重载了<<输出运算符),但是当编译器对表达式求值时w1+1
,似乎很好。怎么可能呢?
例如,如果您有以下类声明,其中包含转换构造函数和转换运算符
struct A
{
A( int x ) : x( x ) {}
operator int() const { return x; }
int x;
};
const A operator +( const A &a1, const A &a2 )
{
return A( a1.x + a2.x );
}
然后声明
a1 + a2;
例如,声明a1和a2的位置
A a1( 10 );
A a2( 20 );
格式正确,因为不需要调用转换函数。这两个操作数都与运算符+的参数声明匹配。
但是,如果您要写例如
a1 + 20;
当编译器由于存在歧义而发出错误时。编译器可以应用转换构造函数A( int )
将第二个操作数转换为type,A
然后调用为type对象定义的运算符A
。也可以应用转换运算符operator int
将第一个操作数转换为type,int
并operator +
为type对象调用内置函数int
。
为了避免这种歧义,您可以使用函数specifier声明构造函数或运算符(或两者)explicit
。
例如
explicit A( int x ) : x( x ) {}
要么
explicit operator int() const { return x; }
在这种情况下,将只存在一个隐式转换,并且没有歧义。
我想补充一下上面的描述,即使某些converion运算符可以用函数说明符声明,有时也可以隐式调用explicit
。
例如,根据C ++标准(6.4选择语句)
- ...作为表达式的条件的值是该表达式的值,对于switch以外的语句在上下文中转换为bool;
和(5.16条件运算符)
1条件表达式从右到左分组。第一个表达式在上下文中转换为bool(第4条)。
因此,例如,如果上面的类具有使用函数说明符声明的以下转换运算符 explicit
explicit operator bool() const { return x != 0; }
但是,例如在以下语句中将隐式调用它
A a( 10 );
std::cout << ( a ? "true" : "false" ) << std::endl;
在这里,a将在条件运算符中转换为bool类型的对象。
编辑:更新您的问题后此表达式
w1+1;
是运算符的完全匹配
wrapper operator+(int);
都不需要转换。因此,代码可以成功编译。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句