类型转换操做符operator type(),是不一样于重载()操做符operator()()的,更不一样于类构造函数 classname() ios
类型转换操做符(type conversion operator)是一种特殊的类成员函数,它定义将类类型值转变为其余类型值的转换。转换操做符在类定义体内声明,在保留字 operator 以后跟着转换的目标类型。boost::ref和boost::cref就使用到了类型转换操做符。 数组
函数原型
T1::
operator
T2()
const
;
//
T1的成员函数,"(T2)a"类型转换
1. 转换函数必须是成员函数,不能指定返回类型,而且形参表必须为空;返回值是隐含的,返回值是与转换的类型相同的,即为上面原型中的T2; 函数
2. T2表示内置类型名(built-in type)、类类型名(class type)或由类型别名(typedef)定义的名字;对任何可做为函数返回类型的类型(除了 void 以外)均可以定义转换函数,通常而言,不容许转换为数组或函数类型,转换为指针类型(数据和函数指针)以及引用类型是能够的; ui
3. 转换函数通常不该该改变被转换的对象,所以转换操做符一般应定义为 const 成员; spa
4. 支持继承,能够为虚函数; 指针
5. 只要存在转换,编译器将在可使用内置转换的地方自动调用它; 对象
for an example:
#include
<
iostream
>
using
namespace
std;
class
D{
public
:
D(
double
d):
d_(d){}
operator
int
()
const
{
cout
<<
"
(int)d called!!
"
<<
endl;
return
static_cast
<
int
>
(d_);
}
private
:
double
d_;
};
int
add(
int
a,
int
b){
return
a
+
b;
}
int
main(){
D d1
=
1.1
;
D d2
=
2.2
;
cout
<<
"
add(d1,d2)=
"
<<
add(d1,d2)
<<
endl;
return
0
;
}
(int)d called!!
(int)d called!!
add(d1,d2)=3
Press any key to continue
类型转换构造函数(conversion constructor)
先来讲下类型转换构造函数:C++中的explicit用来修饰类的构造函数,代表该构造函数是显示的,既然有显示的,那么就有隐式的
若果一个类的构造函数时一个单自变量的构造函数,所谓的单自变量是可能声明一个单一参数,也可能声明一个拥有多个参数,而且除了第一参数外都其余参数都有默认值
这样的constructor称为单自变量constructor.
若果类中有这样一个constructor那么在编译的时候编译器将会产生一个省却的操做:将该constructor参数对应 的 数据类型 的 数据转换为该类的对象
class MyClass
{
public:
MyClass( int num );
}
....
MyClass obj = 10; //ok,convert int to MyClass 继承
在上面的操做中编译器其实产生代码以下:
Myclass temp(10);
Myclass obj=temp;
若果要避免编译器产生上诉的隐式转换,那么此时explicit将产生做用。
explicit的做用:
explicit关键字将做用在类的构造函数,被修饰的构造函数,将再不能发生隐式转换了,只能以显示的进行类型转换
explicit 的注意:
只能做用在类的内部的构造函数上
只能做用在单自变量的构造函数上
ci
class
Circle {
public
:
Circle(
double
r) : R(r) {}
Circle(
int
x,
int
y
=
0
) : X(x), Y(y) {}
Circle(
const
Circle
&
c) : R(c.R), X(c.X), Y(c.Y) {}
private
:
double
R;
int
X;
int
Y;
};
int
main(){
Circle A
=
1.23
;
//
发生隐式类型转换
//
编译器会将它变成以下代码
//
tmp = Circle(1.23)
//
Circle A(tmp);
//
tmp.~Circle();
Circle B
=
123
;
//
注意是int型的,调用的是Circle(int x, int y = 0)
//
它虽然有2个参数,但后一个有默认值,任然能发生隐式转换
Circle C
=
A;
//
这个算隐式调用了拷贝构造函数
return
0
;
}
加了explicit关键字后,可防止以上隐式类型转换发生 原型
class
Circle {
public
:
explicit
Circle(
double
r) : R(r) {}
explicit
Circle(
int
x,
int
y
=
0
) : X(x), Y(y) {}
explicit
Circle(
const
Circle
&
c) : R(c.R), X(c.X), Y(c.Y) {}
private
:
double
R;
int
X;
int
Y;
};
int
_main() {
//
一下3句,都会报错
//
Circle A = 1.23;
//
Circle B = 123;
//
Circle C = A;
//
只能用显示的方式调用了
//
未给拷贝构造函数加explicit以前能够这样
Circle A
=
Circle(
1.23
);
Circle B
=
Circle(
123
);
Circle C
=
A;
//
给拷贝构造函数加了explicit后只能这样了
Circle A(
1.23
);
Circle B(
123
);
Circle C(A);
return
0
;
}
类型转换操做符 vs 类型转换构造函数(conversion constructor)
有时候使用conversion constructor就能实现类型转换,这种方式效率更高并且也更直观,下面举例说明:
1
#include
<
iostream
>
2
using
namespace
std;
3
class
A{
4
public
:
5
A(
int
num
=
0
)
6
:dat(num){
7
cout
<<
"
A单参数构造函数called!!
"
<<
endl;
8
}
9
operator
int
(){
10
cout
<<
"
A::operator int() called!!
"
<<
endl;
11
return
dat;
12
}
13
private
:
14
int
dat;
15
};
16
17
class
X{
18
public
:
19
X(
int
num
=
0
)
20
:dat(num){
21
cout
<<
"
X单参数构造函数called!!
"
<<
endl;
22
}
23
operator
int
(){
24
cout
<<
"
X::operator int() called!!
"
<<
endl;
25
return
dat;
26
}
27
operator
A(){
28
cout
<<
"
operator x() called!!
"
<<
endl;
29
A temp
=
dat;
30
return
temp;
31
}
32
private
:
33
int
dat;
34
};
35
36
int
main(){
37
cout
<<
"
///////trace more///////
"
<<
endl;
38
A more
=
0
;
39
40
cout
<<
"
///////trace stuff///////
"
<<
endl;
41
X stuff
=
2
;
42
43
cout
<<
"
//////trace hold dingyi//////
"
<<
endl;
44
int
hold;
45
46
cout
<<
"
///////trace hold=stuff//////
"
<<
endl;
47
hold
=
stuff;
48
cout
<<
"
///////two trace hold=stuff//////
"
<<
endl;
49
cout
<<
"
hold:
"
<<
hold
<<
endl;
50
51
cout
<<
"
//////trace more=stuff//////
"
<<
endl;
52
more
=
stuff;
53
cout
<<
"
//////two trace more=stuff//////
"
<<
endl;
54
cout
<<
"
more:
"
<<
more
<<
endl;
55
56
return
0
;
57
}
上面这个程序中X类经过“operator A()”类型转换来实现将X类型对象转换成A类型,这种方式须要先建立一个临时A对象再用它去赋值目标对象;更好的方式是为A类增长一个构造函数:
A(
const
X
&
rhs) : dat(rhs) {}
同时,请注意上面程序的more的类型在调用std::cout时被隐式地转成了int!
一个简单boost::ref实现
经过重载type conversion operator,咱们就能够本身实现一个简版的boost::ref。
1
#include
<
iostream
>
2
3
template
<
class
T
>
4
class
RefHolder{
5
public
:
6
RefHolder(T
&
ref
) : ref_(
ref
) {}
7
8
/*
“(T&)A”类型转换操做符
*/
9
operator
T
&
()
const
{
10
return
ref_;
11
}
12
private
:
13
T
&
ref_;
14
};
15
16
17
template
<
class
T
>
18
inline RefHolder
<
T
>
ByRef(T
&
t) {
19
return
RefHolder
<
T
>
(t);
20
}
21
22
int
inc(
int
&
num) {
23
num
++
;
24
return
num;
25
}
26
27
28
int
main() {
29
int
n
=
1
;
30
std::cout
<<
inc(ByRef(n))
<<
std::endl;
//
RefHolder<int>被转换成了"int&"类型
31
32
return
0
;
33
}
34
35