从类类型到类类型的隐式转换
implicit conversions from and to class types
我正在学习c++中的转换构造函数和转换操作符。到目前为止,我学到的是,任何只接受一个参数(和任意数量的可选默认参数)的非显式构造函数都表示隐式的类类型转换为该类类型,例如,如果一个类定义了一个构造函数,具有一个类型为int
的参数,我可以在需要该类类型的对象时使用int
:
(假设class_type有重载的+=操作符)
class_type a;
a+=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++)不会发出任何模糊的调用错误!
这是类头(以及非成员操作符+函数声明):
#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
的转换操作符(我还重载了<<输出操作符,以便打印一些结果),但是当编译器计算表达式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 )
将第二个操作数转换为A
类型,也可以调用为A
类型对象定义的操作符。也可以应用转换操作符operator int
将第一个操作数转换为类型int
,并为类型int
的对象调用内置的operator +
。
为了避免这种歧义,可以使用函数说明符explicit
声明构造函数或操作符(或两者)。
explicit A( int x ) : x( x ) {}
或
explicit operator int() const { return x; }
在这种情况下,只有一个隐式转换存在,并且没有歧义。
我想附加上面的描述,有时某些转换操作符可以隐式调用,即使它们是用函数说明符explicit
声明的。
- …方法的值作为条件的值表达式,在上下文中为语句other转换为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);
两种转换都不需要。因此代码编译成功。
你可以很容易地尝试一下,看看编译器是怎么做的:
#include <iostream>
struct ABC {
int v;
ABC(int x) : v(x) { }
operator int() const { return v; }
void operator +=(ABC const &that) {
v += that.v;
}
};
ABC operator+(ABC const &lhs, ABC const &rhs) {
return { lhs.v + rhs.v };
}
int main() {
ABC a(5);
std::cout << a + 1 << 'n';
a += 10;
std::cout << a << 'n';
}
GCC如果我定义了一个重载+操作符,将两个class_type对象作为其参数会怎样?
错误:'operator+'的歧义重载(操作数类型为'ABC'和'int')
编译器看到两个候选:operator+(int, int) <built-in>
和ABC operator+(const ABC&, const ABC&)
。这意味着它不仅可以隐式地将a + 5
中的5
转换为a
,还可以将a
转换为int
。完成这些转换后,两个operator+
函数都成为潜在的匹配。
编译器应该如何知道通过函数匹配调用哪一个?
它不知道这个错误。
到
int
的转换只在只定义内置操作符时隐式发生吗?
是的,否则它不会自动将class_type
转换为int
。但是,int
到class_type
将隐式发生,除非您使class_type
的构造函数explicit
:
explicit ABC(int x) : v(x) { }
如果您可以访问c++ 11,那么您也可以显式地设置转换函数:
explicit operator int() const { return v; }
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++中的双指针类型转换
- 逐位操作的隐式类型转换
- 模板中的类型转换
- 在 C++(和 C)中进行类型转换时明显不一致
- 字符类型转换不兼容
- 将复杂的非基元C++数据类型转换为 Erlang/Elixir 格式,以使用 NIF 导出方法
- C++:用户定义的显式类型转换函数错误
- 将类指针类型转换为键时出错
- 通过引用传递参数时C++类型转换
- 在 C++ 中将一个模板类型的对象类型转换为另一个模板类型
- C++显式类型转换(C 样式强制转换)的强制表示法和static_cast的多种解释
- C++无效的函数类型转换
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- 如何将Windows产品类型转换为名称?
- 通过构造函数方法输出的类到类类型转换是 5500 为什么不是 5555
- 事件系统:使用类型转换或联合进行继承
- 如何在参数中定义隐式类型转换的构造函数?
- 类模板实例化中的类型转换