自动类型转换:a.构造函数转换 b.运算符转换。
构造函数转换:如果定义一个构造函数,它把另一个类型对象或引用作为它的单个参数,那么这个构造函数允许编译器执行自动类型转换。
class One {
public:
One() {}
};
class Two {
public:
Two(const One&) {}//one->two;
};
void f(Two) {}
int main() {
One one;
f(one); // Wants a Two, has a One
} ///:~
26.加上explicit阻止自动转换,得手动!加上explicit
class One {
public:
One() {}
};
class Two {
public:
explicit Two(const One&) {}
};
void f(Two) {}
int main() {
One one;
//f(one); //失败的
f(Two(one));
} ///:~
运算符转换:创建一个成员函数,这个函数通过在关键字operator后跟随想要转
换到的类型的方法,将当前类型转换为希望的类型
class Three {
int i;
public:
Three(int ii = 0, int = 0) : i(ii) {}
};
class Four {
int x;
public:
Four(int xx) : x(xx) {}
operator Three() const { return Three(x); }
};
void g(Three) {}
int main() {
Four four(1);
g(four);///执行 operator Three();
g(1); // 执行 Three(1,0)
} ///:~
使用全局重载运算符而不用成员运算符的最便利的原因之一是在全局版本中的自动类型转换可以针对左右任一操作数,而成员版本必须保证左侧操作数已处于正确的
形式。如果向两个操作数都被转换,全局版本可以节省很多代码
class Number {
int i;
public:
Number(int ii = 0) : i(ii) {}//必须有这个构造函数,才会转换啊!
const Number
operator+(const Number& n) const {///成员
return Number(i + n.i);
}
friend const Number//友元
operator-(const Number&, const Number&);
};
const Number
operator-(const Number& n1,
const Number& n2) {
return Number(n1.i - n2.i);
}
int main() {
Number a(47), b(11);
a + b; // OK
a + 1; // 2nd arg converted to Number
//! 1 + a; // Wrong! 1st arg not of type Number
a - b; // OK
a - 1; // 2nd arg converted to Number
1 - a; // 1st arg converted to Number
} ///:
29.‘
例子
class Stringc {
string s;
public:
Stringc(const string& str = "") : s(str) {}
operator const char*() const {
return s.c_str();
}
};
int main() {
Stringc s1("hello"), s2("there");
strcmp(s1, s2); // Standard C function
strspn(s1, s2); // Any string function!
} ///:~因为编译器知道如何从string转换到char*,所以现在任何一个接受char*参数的函数也可以接受string参数
30.自动类型转换应小心使用,同所有重载的运算符相比,它在减少代码方面是非常出色的,但不值得无缘无故地使用。