类型转换操作符&&C++重载输出流运算符

在将一种类型转换为另一种类型的时候,直接使用强制类型转换往往不能做到无缝转换,C++提供了类型转换操作符将类转换为特定的类型。

类型转换操作符

使用实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Test{
public:
Test(int a, std::string c):_a(a), _c(c) {}
//类型转换操作符:将Test转换为int类型
operator int() const {return _a;}
//Test转换为string类型
operator std::string() const {return _c;}
private:
int _a;
std::string _c;
};
int main() {
Test t(1, "qwe");
std::cout << "t=" << t << std::endl; //t=1
std::cout << "t=" << std::string(t) << std::endl; //t=qwe
return 0;
}

分析

从上面可以看出,我们可以通过operator type()来进行类型转换。当同时定义两种类型转换的时候,默认会调用哪一种类型转换呢?
这个和C++输出流的实现有关。

C++重载输出流运算符

在实际运用中,我们通常有将自定义的一个类中的一些信息打印出来的需求,这个时候可以使用重载输出流运算符来实现。
而实现的当时有多种,最常见的是通过友元和全局函数重载输出流运算符

流输出运算符

在C++中类basic_ostream有成员函数operator<<(int),而没有成员函数operator << (const std::string),
故上面有限调用同名的成员函数,所以默认输出int,若同时定义了int和float的类型转换,这个时候就需要强制类型转换,否则会出现二义性。

使用友元方式重载流输出运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Test{
public:
Test(int a, std::string c):_a(a), _c(c) {}
friend std::ostream& operator<< (std::ostream& os, const Test& t) {
os << t._a << " " << t._c << std::endl;
return os;
}
private:
int _a;
std::string _c;
};
int main() {
Test t(1, "qwe");
std::cout << t << std::endl;
return 0;
}

使用全局重载流输出运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <string>
#include <fstream>
class Test{
public:
Test(int a, std::string c):_a(a), _c(c) {}
public:
int _a;
std::string _c;
};
std::ostream& operator << (std::ostream& os, const Test& t) {
os << t._a << " " << t._c << std::endl;
return os;
}
int main() {
Test t(1, "qwe");
std::cout << t << std::endl;
std::cout << std::string(t) << std::endl;
std::cout << t << std::endl;
return 0;
}

类内部重载流输出操作符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <string>
#include <fstream>
class Test{
public:
Test(int a, std::string c):_a(a), _c(c) {}
std::ostream& operator<< (std::ostream& os) {
os << _a << " " << _c << std::endl;
return os;
}
public:
int _a;
std::string _c;
};
int main() {
Test t(1, "qwe");
//注意此时为Test的成员函数,所以要通过成员函数的方法来调用
t.operator<<(std::cout) << std::endl;
return 0;
}

为什么重载+号运算符不需要使用类成员的方式调用,因为+号运算符的做操作数为当前类。