要点
原型:operator typeName();
比如说转换为double类型的函数原型如下:
operator double();
1.1
/*1.转换函数,用于将类类型转换为某种类型(比如整型)
2.而构造函数可以将某种类型转换为类类型。这两个函数的作用是相反的。
3.转换函数是用户定义的强制转换类型,可以像使用强制转换类型那样使用它们
*/
#include
using namespace std;
class Stonewt
{
private:
enum{Lbs_per_stn=14}; //一磅等于14石,磅和石都是一种重量单位
int stone; //石
double pds_left; //不够1石的部分
double pounds; // 磅
public:
Stonewt(double lbs); //构造函数,这个构造函数只接受一个参数,可以作为转换函数,和通常的转换函数不一样,或者说叫转换构造函数更换好
};
Stonewt(double llbs)是构造函数,这个构造函数只接受一个参数,可以作为转换函数,和通常的转换函数不一样,这里实现的是从普通类型到类类型的转换。它在以下几个地方使用
1.初始化对象接受一个double参数的时候
Stonewt st(20.3);//这将创建一个对象,并将其成员初始化
2.一个double变量赋值给Stonewt对象的时候
Stonewt st; //(1)
st=20.3; //(2)
上面(1)将会创建一个对象,但是没有初始化。
(2)有点复杂,希望如果有错误的话,可以指出来。这也是个人猜想。
第(2)条语句的步骤:
Stonewt& operator=(Stonewt st); //默认赋值运算符,注意没有引用
那么会怎么样呢?将会这样:
Stonewt &operator=(Stonewt st(20.3)); //(3)
那么显然(3)的参数括号里面会调用构造函数,是不是有点套娃的感觉
3.返回值被声明为Stonewt的时候
Stonewt xxxx(xxx)
{
...
return x; //如果x是double类型的,那么将会先先转换为一个临时的Stonewt变量,然后赋值给接受返回值的对象。
}
继续上面的类的定义
1.2
#include
using namespace std;
class Stonewt
{
private:
enum{Lbs_per_stn=14}; //一磅等于14石,磅和石都是一种重量单位
int stone;
double pds_left;
double pounds;
public:
Stonewt(double lbs); //构造函数,这个构造函数只接受一个参数,可以作为转换函数,和通常的转换函数不一样,或者说叫转换构造函数更换好
Stonewt(int stn, double lbs); //两个参数的构造函数就不能作为转换函数了
Stonewt(); //默认构造函数
~Stonewt(); //析构函数
void show_lbs()const; //输出英镑
void show_stn()const; //输出石
operator int()const; //转换函数,将Stonewt类转换为int类型
operator double()const; //转换函数,将Stonewt类转换为double类型
};
说明一下转换函数:
1.3,cpp
/*
1.转换函数,用于将类类型转换为某种类型(比如整型)
2.而构造函数可以将某种类型转换为类类型。这两个函数的作用使相反的。
3.转换函数是用户定义的强制转换类型,可以像使用强制转换类型那样使用它们
*/
#include
using namespace std;
class Stonewt
{
private:
enum{Lbs_per_stn=14}; //1石等于14磅,磅和石都是一种重量单位
int stone;
double pds_left;
double pounds;
public:
Stonewt(double lbs) { pounds = lbs; } //构造函数,这个构造函数只接受一个参数,可以作为转换函数,和通常的转换函数不一样,这里实现的
//是从普通类型到类类型的转换。它在以下几个地方使用
//1.初始化对象接受一个double参数的时候 2.一个double变量赋值给Stonewt对象的时候
//详细讲一下第二点:
Stonewt(int stn, double lbs); //两个参数的构造函数就不能作为转换函数了
Stonewt();
~Stonewt();
void show_lbs()const; //输出英镑
void show_stn()const; //输出石
operator int()const; //转换函数,将Stonewt类转换为int类型
operator double()const; //转换函数,将Stonewt类转换为double类型
};
Stonewt::Stonewt(double lbs)
{
stone = int(lbs) / Lbs_per_stn; //1石等于磅的数量除14
pds_left = int(lbs) % Lbs_per_stn + lbs - int(lbs); //不够1石的磅
pounds = lbs; //磅
}
Stonewt::Stonewt(int stn, double lbs)
{
stone = stn; //石
pds_left = lbs;
pounds = stn * Lbs_per_stn + lbs; //磅
}
Stonewt::Stonewt()
{
stone = pounds = pds_left = 0;
}
Stonewt::~Stonewt() //啥也没有
{
}
void Stonewt::show_stn()const
{
cout << stone << " stone, " << pds_left << " pounds\n";
}
void Stonewt::show_lbs()const
{
cout << pounds << " pounds\n";
}
Stonewt::operator int()const
{
return int(pounds + 0.5);
}
Stonewt::operator double()const
{
return pounds;
}
1.3的说明
很显然上面的转换函数没有返回类型,但是函数体里面却使用了return
1.4
Stonewt::operator int()const
{
return int(pounds + 0.5);
}
Stonewt::operator double()const
{
return pounds;
}
int main()
{
Stonewt poppins(9, 2.8);
double p_wt = poppins;
cout << "Convert to double=> ";
cout << "Poppins: " << p_wt << "pounds.\n";
cout << "Convert to int=> ";
cout << "Poppins: " << int(poppins) << " pounds.\n";
return 0;
}
注意,最后一个cout
cout << "Poppins: " << int(poppins) << " pounds.\n";
如果不适用强制类型转换,会怎么样?、
编译器会指出二义性错误,因为该类里面有两个转换函数,编译器不知道用哪一个。
那么如果只有一个转换函数,编译器就不会报错,但是不管有几个转换函数,最好还是使用强制转换!
举个例子:
long gone=poppins; //这会产生二义性
为什么呢会产生二义性呢?因为不论是将poppins转换为int,还是转换为double,都可以赋值给long类型。
那么就需要使用强制类型转换。
long gone=(double)poppins;
long gone=double(poppins);
上面两种方法是一样的。
和转换构造函数(仅仅接受一个参数的构造函数)一样,转换函数提供执行自动,隐式转换的函数所存在的问题是:在用户不希望进行转换的时候,它却转换了。
想必都知道了,,,
explicit !!!
class Stonewt
{
.....
explicit operator int()const;
explicit operator double()const;
}
那么有了这个声明之后,就只能使用强制转换来调用这些函数了,就不能隐式转换了!
假设没有定义operator double()函数。我们来重载加法运算符
/*
1.转换函数,用于将类类型转换为某种类型(比如整型)
2.而构造函数可以将某种类型转换为类类型。这两个函数的作用使相反的。
3.转换函数是用户定义的强制转换类型,可以像使用强制转换类型那样使用它们
*/
#include
using namespace std;
class Stonewt
{
private:
enum{Lbs_per_stn=14}; //1石等于14磅,磅和石都是一种重量单位
int stone;
double pds_left;
double pounds;
public:
Stonewt(double lbs); //构造函数,这个构造函数只接受一个参数,可以作为转换函数,和通常的转换函数不一样,这里实现的
//是从普通类型到类类型的转换。它在以下几个地方使用
//1.初始化对象接受一个double参数的时候 2.一个double变量赋值给Stonewt对象的时候
//详细讲一下第二点:
Stonewt(int stn, double lbs); //两个参数的构造函数就不能作为转换函数了
Stonewt();
~Stonewt();
void show_lbs()const; //输出英镑
void show_stn()const; //输出石
operator int()const; //转换函数,将Stonewt类转换为int类型
operator double()const; //转换函数,将Stonewt类转换为double类型
//Stonewt operator+(const Stonewt& st)const ;
friend Stonewt operator+(const Stonewt& st1, const Stonewt& s2); //友元
friend ostream & operator<<(ostream &os, const Stonewt & st)
{
os << st.pds_left << " " << st.pounds << endl;
return os;
}
};
Stonewt::Stonewt(double lbs)
{
stone = int(lbs) / Lbs_per_stn; //1石等于磅的数量除14
pds_left = int(lbs) % Lbs_per_stn + lbs - int(lbs); //不够1石的磅
pounds = lbs; //磅
}
Stonewt::Stonewt(int stn, double lbs)
{
stone = stn; //石
pds_left = lbs;
pounds = stn * Lbs_per_stn + lbs; //磅
}
Stonewt::Stonewt()
{
stone = pounds = pds_left = 0;
}
Stonewt::~Stonewt() //啥也没有
{
}
void Stonewt::show_stn()const
{
cout << stone << " stone, " << pds_left << " pounds\n";
}
void Stonewt::show_lbs()const
{
cout << pounds << " pounds\n";
}
Stonewt::operator int()const
{
return int(pounds + 0.5);
}
//Stonewt::operator double()const
//{
// return pounds;
//}
//Stonewt Stonewt::operator+(const Stonewt& st)const //重载加法作为类成员函数
//{
// double pds = pounds + st.pounds;
// Stonewt sum(pds);
// return sum;
//}
Stonewt operator+(const Stonewt& st1, const Stonewt& st2)
{
double pds = st1.pounds + st2.pounds;
Stonewt sum(pds);
return sum;
}
int main()
{
Stonewt jennySt(9, 12);
double kenny=129.2;
Stonew total;
total=jennySt+kenny; //先调用加法函数,发现kenny是double类型
//然后又发现有Stonewt(double),那么就可以隐式转换为类类型,然后调用函数。
cout << total;
return 0;
}
注意
如果上面定义了operator double(),那么下面这句话会怎么样:
total=jennySt+kenny; //两种可能
//第一种:kenny通过转换构造函数变成Stonewt类,然后调用重载加法运算符函数
//第二章,jennyst通过operator double()转换为double类型,然后实现两个
//double类型的普通相加
这就意味着会产生二义性。
所以,总结:
要将double类和Stonewt类相加,有两个方法