自动类型转换¶
1、使用构造函数进行自动类型转换¶
两个类,calss One和class Two, class Two的构造函数参数传一个One。那么就可以把类One转为类Two。
如果不想构造函数进行自动类型转换可以在前面加explicit
,这种构造函数只能进行创建对象,不能自动类型转换。
class One {
public:
One(){}
};
class Two {
public:
// explicit Two(const One&) {}
Two(const One&) {}
};
void f(Two) {}
void test() {
One one;
// f(Two(one));
f(one);
}
2、使用运算符进行自动类型转换,类似运算符重载¶
把Four变成Three,参数传four会自动的转变为three。
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) {}
调用:
four变成three是用的上面的利用运算符转换
1变成three是用的Three的构造函数
void test() {
Four four(1);
g(four);//four -> three
g(1);//1 -> three
}
都发生了自动类型转换。
例:整型转为Number类型
//整型转为Number类型
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);
}
调用测试:
void test() {
Number a(47), b(11);
a + b;
a + 1; //1 -> Number
//1 + a;
a - b;
a - 1; //1 -> Number
1 - a; //1 -> Number
}
1+a不可以。加法是一个成员函数,只有一个参数。
1-a可以,减法是友元,全局函数,两个参数。1会变成Number。
自动类型优缺点¶
优点¶
自定义的字符串类,字符串类有很多方法,长度,字符串比较等等。要把所有的字符串操作函数都做出来就太多了。
如果使用自动类型转换就不用写那么多方法了。
使用自动类型转换,变成C语言的字符串。
class MyString {
string s;
public:
MyString(const string& str = "") : s(str) {}
// int strcmp(const MyString& S) const {
// return ::strcmp(s.c_str(), S.s.c_str());
// }
operator const char*() const {
return s.c_str();
}
};
然后就可以直接使用标准库里的函数去比较。
void test() {
MyString s1("Hello"), s2("there");
// s1.strcmp(s2);
::strcmp(s1, s2);
::strspn(s1, s2);
}
库函数都可以使用。不用在新定义的类里面重写一遍。重写一遍很繁琐。
缺点¶
把苹果变成橘子
- 利用运算符把苹果变成橘子
- 利用构造函数把苹果变成橘子
class Orange {
public:
// Orange(Appple);
};
class Pear {};
class Apple {
public:
operator Orange() const { return Orange(); }
operator Pear() const { return Pear(); }
// Orange toOrange();
// Orange makeOrange();
// Pear toPear();
// Pear makePear();
};
void k(Orange) {}
void eat(Orange);
void eat(Pear);
void test() {
Apple apple;
k(apple);
// eat(apple);
}
两种方法都有的时候,C++不知道使用哪个方法把苹果变成橘子
解决方法就是不要写两种方法,只用一种就可以了。
苹果可以变成橘子,苹果可以变成梨。吃苹果的时候,C++不知道变哪个。不做成自动类型转换。用成员函数明确的显示的转换。而不是自动类型转换。
class Apple {
public:
// operator Orange() const { return Orange(); }
// operator Pear() const { return Pear(); }
Orange toOrange();
Orange makeOrange();
Pear toPear();
Pear makePear();
};
fo转换成Fee
class Fi{};
class Fee {
public:
Fee(int) {}
Fee(const Fi&) {}
};
class Fo {
int i;
public:
Fo(int x = 0) : i(x) {}
operator Fee() const { return Fee(i); }
};
void test() {
Fo fo;
Fee fee = fo;//fo -> fee
}
fo转换成Fee。Fee有C++默认赋值运算符重载。非常灵活。
只做必要的类型转换,不要做过多的类型转换,容易出错。合理使用。