当一个值拷贝给另一个兼容类型的值时,隐式转换会自动进行。
short a=2000;
int b;
b=a;
数字的隐式转换可能会存在数据丢失(数据截断)
对于非基本类型,数组和函数可以隐式转换成指针。
不同类型间的指针也允许互相转换。
- NULL 指针允许转换成任意类型的指针。
- 任意类型的指针可以转换成 void 指针。
- 派生类的指针可以转换成基类指针,但是不会改变它的 const 或者 volatile 属性。
- T* 可以转换成 const T*,但反过来不行。
除了上述内置的隐式转换,C++ 允许用户自定义类型转换。在类中有两种方式:
- 类型转换操作符(Typecast Operators)
- 转换构造函数(Converting Constructors)
第一个例子。
自定义了 Vector 结构,通过重载 bool 操作符,可以将 Vector 当作 bool 变量使用,当 x && y && && z 为 true 时,Vector 就为 true,否则为 false。
#include <iostream>
struct Vector {
float x;
float y;
float z;
// Return true if all of the components
// of the vector are truthy
operator bool() const {
return x && y && z;
}
};
int main() {
Vector A { 1, 2, 3 };
Vector B { 0, 0, 0 };
// We can now treat Vectors as booleans
if (A) {
std::cout << "A is Truthy";
}
if (B) {
std::cout << "B is Truthy";
}
}第二个例子。
在 Player 中定义了一个 operator Party() ,达到将 Player 转换成 Party 的功能。
#include <iostream>
// Forward-declaring an incomplete type so
// it can be used within the Party class
class Player;
class Party {
public:
Party(const Player* Leader)
: Leader { Leader } {
std::cout << "A party was created\n";
}
const Player* Leader;
};
class Player {
public:
std::string Name;
// Allow a Player to be converted to a Party
operator Party() const {
return Party { this };
}
};
// This function accepts parties - not players
void StartQuest(Party Party) {
std::cout << Party.Leader->Name
<< "'s party has started the quest";
}
int main() {
Player Frodo { "Frodo" };
// Because Players can now be implicitly
// converted to parties we can pass a Player
// argument into a Party parameter
StartQuest(Frodo);
}如果一个类定义了一个非 explicit 的单参数构造函数,实际上就允许参数类型自动转换成该类型。
struct Vector {
Vector(float ComponentSize) :
x { ComponentSize },
y { ComponentSize },
z { ComponentSize } {}
float x;
float y;
float z;
};
void Move(Vector Direction) {
// ...
}
int main() {
Move(5.f);
}
更为恼火的是下面的代码仍然能够编译通过。
...
void Move(Vector Direction) {
// ...
}
int main() {
Move(true);
}实际上 true 隐式转换成了 float,然后 float 通过转换构造函数转换成了 Vector 类型。
为了避免这些隐式转换,可以在函数声明标记 explicit。
struct Vector {
explicit Vector(float ComponentSize) :
x { ComponentSize },
y { ComponentSize },
z { ComponentSize } {}
....
}struct MyType {
// 添加 explicit 关键字,禁止通过该操作符进行隐式转换
explicit operator int() {
return 1;
}
};