類對象和其他類型對象的轉換
轉換場合有:
賦值轉換
表達式中的轉換
顯式轉換
函數調用,
傳遞參數時的轉換 轉換方向有:
由定義類向其他類型的轉換
由其他類型向定義類的轉換
#include <math.h>
#include <iostream>
using std::cout;
using std::endl;
class Complex
{
public:
Complex(double dreal, double dimag)
: _dreal(dreal)
, _dimag(dimag)
{}
void display() {
cout << _dreal << " + " << _dimag << "i" << endl;
}
friend std::ostream & operator<<(std::ostream & os, const Complex & rhs);
private:
double _dreal;
double _dimag;
};
std::ostream & operator<<(std::ostream & os, const Complex & rhs)
{
if(rhs._dreal == 0 && rhs._dimag != 0)
os << rhs._dimag << "i";
else {
os << rhs._dreal;
if(rhs._dimag > 0)
os << " + " << rhs._dimag << " i";
else if (rhs._dimag < 0)
os << " - " << rhs._dimag * (-1) << " i";
}
return os;
}
class Point
{
public:
Point(int ix = 0, int iy = 0)
: _ix(ix)
, _iy(iy)
{
cout << "Point(int=0, int=0)" << endl;
}
//由自定義類型向其他類型進行轉換
//
//類型轉換函數
//1. 必須是成員函數
//2. 沒有返回值類型
//3. 在函數體內必須用return 語句以傳值方式返回一個目標類型的變量(對象)
//4. 沒有形參
//5. 一般情況下,不要使用它, 因為它違反了常規思維方式
operator int()
{
cout << "operator int()" << endl;
return _ix;
}
operator double()
{
cout << "operator double()" << endl;
return _ix * _iy;
}
operator Complex()
{
cout << "operator Complex()" << endl;
return Complex(_ix, _iy);
}
void print() const
{
cout << "(" << _ix
<< "," << _iy
<< ")" << endl;
}
friend std::ostream & operator<<(std::ostream & os, const Point & rhs);
private:
int _ix;
int _iy;
};
std::ostream & operator<<(std::ostream & os, const Point & rhs)
{
os << "(" << rhs._ix
<< "," << rhs._iy
<< ")";
return os;
}
int main(void)
{
Point pt1(1, 2);
int x = pt1;
cout << "x = " << x << endl;
double dvalue = pt1;
cout << "dvalue = " << dvalue << endl;
Complex cx = pt1;
cout << "cx = " << cx << endl;
return 0;
}
由其他類型向定義類的轉換
- 由其他類型(如int、double)等向自定義類的轉換是由構造函數來實現的,只有當類的定義和實現中提供了合適的構造函數時,轉換才能通過。什么樣的構造函數才是合適的構造函數呢?主要有以下幾種情況,為便於說明,假設由int類型向自定義point類轉換:
- point類的定義和實現中給出了僅包括只有一個int類型參數的構造函數 Point pt1 = 5;
- point類的定義和實現中給出了包含一個int類型參數,且其他參數都有缺省值的構造函數
- point類的定義和實現中雖然不包含int類型參數,但包含一個非int類型參數如float類型,此外沒有其他參數或者其他參數都有缺省值,且int類型參數可隱式轉換為float類型參數。
- 在構造函數前加上關鍵字explicit可以關閉隱式類型轉換
//9-12 由其他類型轉換到自定義類型
#include <iostream>
using namespace std;
class point;
class anotherPoint //anotherPoint類定義
{
private: //private成員列表
double x;
double y;
public:
anotherPoint(double xx = 1, double yy = 1) //構造函數,帶缺省參數值
{
x = xx;
y = yy;
}
void print() //輸出函數,點的信息
{
cout << "( " << x << " , " << y << " )";
}
friend class point; //使point類成為本類的友元類, 這樣point
//類就可以訪問anotherPoint 類的private變量了
};
class point //point類定義
{
private: //private成員列表
int xPos;
int yPos;
public:
// explicit //如果在構造函數前加上explicit, 就不允許 point pt1 = 5這種隱式轉換了
point(int x = 0, int y = 0) //構造函數,帶缺省參數,兩個int型變量
{
xPos = x;
yPos = y;
}
point(anotherPoint aP) //構造函數,參數為anotherPoint類對象
{
xPos = aP.x; //由於point類是anotherPoint類的友元類,
yPos = aP.y; //因此這里可以訪問anotherPoint的私有變量x和y
}
void print() //輸出函數,點的信息
{
cout << "( " << xPos << " , " << yPos << " )" << endl;
}
};
int main()
{
//1. 將int類型數字5轉換成point類型
point p1; //創建point類對象p1,采用帶缺省參數的構造函數,即x=0、y=0
cout << 5 << " 轉換成 ";
p1 = 5; //等價於p1=point(5,0);
p1.print(); //輸出點p1的信息
//2. 將double類型變量dX轉換成point類型
double dX = 1.2; //聲明一個double變量dX
cout << dX << " 轉換成 ";
p1 = dX; //等價於p1=point(int(dX),0)
p1.print(); //輸出點p1的信息
//3. 將anotherPoint類型轉換成point類型
anotherPoint p2(12.34, 56.78); //創建anotherPoint類的對象p2
p2.print();
cout << " 轉換成 ";
p1 = p2; //等價於p1=point(p2);
p1.print(); //輸出點p1的信息
//4. 測試在point構造函數前加上explicit以阻止隱性轉換的情況
return 0;
}
類型轉換函數
- 可以通過operator int()這種類似操作符重載函數的類型轉換函數來實現由自定義類型向其他類型的轉換。如將point類轉換成int類型等。
- 在類中定義類型轉換函數的形式一般為:
operator 目標類型名();
- 有以下幾個使用要點:
- 轉換函數必須是成員函數,不能是友元形式。
- 轉換函數不能指定返回類型,但在函數體內必須用return語句以傳值方式返回一個目標類型的變量。
- 轉換函數不能有參數。
//類型轉換函數(由類轉換成其他類型)
#include <iostream>
using namespace std;
class point;
ostream & operator<<(ostream &os, const point &pt);
class anotherPoint //anotherPoint類定義
{
private: //private成員列表
double x;
double y;
public:
anotherPoint(double xx = 1.11, double yy = 1.11)//構造函數,帶缺省參數值
{
x = xx;
y = yy;
}
void print() //成員函數,輸出點的信息
{
cout << "( " << x << " , " << y << " )" << endl;
}
};
class point //Point類定義
{
private: //private成員列表
int xPos;
int yPos;
public:
point(int x = 0, int y = 0) //構造函數,帶缺省參數值
{
xPos = x;
yPos = y;
}
void print() //成員函數,輸出點的信息
{
cout << "( " << xPos << " , " << yPos << " )" << endl;
}
friend ostream & operator<<(ostream &os, const point &pt); // 重載<<運算符
operator int() //定義Point向int型的轉換函數int()
{
return xPos;
}
operator double() //定義Point向double型的轉換函數double()
{
return xPos * yPos;
}
operator anotherPoint() //定義Point向anotherPoint型的轉換函數anotherPoint()
{
return anotherPoint(xPos, yPos);
}
};
ostream & operator<<(ostream &os, const point &pt)
{
os << (pt.xPos * 100);
return os;
}
int main()
{
point p1(4, 5); //聲明一個point類變量p1
p1.print();
//1. point轉換成int
int x1 = p1; //p1賦值給一個int型變量,point中的轉換函數int()被隱式調用
cout << x1 << endl;
//2. point轉換成double
double dX = p1; //p1賦值給一個double型變量,point中的轉換函數double()被隱式調用
cout << dX << endl;
//3. point轉換成anotherPoint
anotherPoint p2; //聲明anotherPoint類對象p2,構造函數采用缺省值
p2 = p1; //p1賦值給p2,point中的轉換函數anotherPoint()被隱式調用
//等價於p2=anotherpoint(p1.xPos,p1.yPos)
p2.print(); //看p2是否修改成功
return 0;
}
