面向对象进阶--转换构造函数,重载,类型转换函数

转换构造函数

1.将其他类型转换为当前类类型需要借助转换构造函数。

具体看例子:点击

 

类型转换函数

1.将当前类类型转换为其他类型,只能出现在类中。

 

2.语法格式:

operator type(){
    //TODO:
    return data;
}

operator 是 C++ 关键字,type 是要转换的目标类型,data 是要返回的 type 类型的数据。

具体点击

 

再谈转换构造函数和类型转换函数(例子)

具体点击

 

类型转换的本质

具体点击

 

四种类型转换运算符

static_cast     dynamic_cast      const _cast和reinterpret_cast

 

关键字说明
static_cast 用于良性转换,一般不会导致意外发生,风险很低。
const_cast 用于 const 与非 const、volatile 与非 volatile 之间的转换。
reinterpret_cast 高度危险的转换,这种转换仅仅是对二进制位的重新解释,不会借助已有的转换规则对数据进行调整,但是可以实现最灵活的 C++ 类型转换。
dynamic_cast 借助 RTTI,用于类型安全的向下转型(Downcasting)。

 

static_cast关键字

1.static_cast 只能用于良性转换,这样的转换风险较低,一般不会发生什么意外,例如:

  • 原有的自动类型转换,例如 short 转 int、int 转 double、const 转非 const、向上转型等;
  • void 指针和具体类型指针之间的转换,例如void *int *char *void *等;
  • 有转换构造函数或者类型转换函数的类与其它类型之间的转换,例如 double 转 Complex(调用转换构造函数)、Complex 转 double(调用类型转换函数)。


需要注意的是,static_cast 不能用于无关类型之间的转换,因为这些转换都是有风险的,例如:

  • 两个具体类型指针之间的转换,例如int *double *Student *int *等。不同类型的数据存储格式不一样,长度也不一样,用 A 类型的指针指向 B 类型的数据后,会按照 A 类型的方式来处理数据:如果是读取操作,可能会得到一堆没有意义的值;如果是写入操作,可能会使 B 类型的数据遭到破坏,当再次以 B 类型的方式读取数据时会得到一堆没有意义的值。
  • int 和指针之间的转换。将一个具体的地址赋值给指针变量是非常危险的,因为该地址上的内存可能没有分配,也可能没有读写权限,恰好是可用内存反而是小概率事件。

 

 

 1 #include <iostream>
 2 #include <cstdlib>
 3 using namespace std;
 4 
 5 class Complex{
 6 public:
 7     Complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ }
 8 public:
 9     operator double() const { return m_real; }  //类型转换函数
10 private:
11     double m_real;
12     double m_imag;
13 };
14 
15 int main(){
16     //下面是正确的用法
17     int m = 100;
18     Complex c(12.5, 23.8);
19     long n = static_cast<long>(m);  //宽转换,没有信息丢失
20     char ch = static_cast<char>(m);  //窄转换,可能会丢失信息
21     int *p1 = static_cast<int*>( malloc(10 * sizeof(int)) );  //将void指针转换为具体类型指针
22     void *p2 = static_cast<void*>(p1);  //将具体类型指针,转换为void指针
23     double real= static_cast<double>(c);  //调用类型转换函数
24    
25     //下面的用法是错误的
26     float *p3 = static_cast<float*>(p1);  //不能在两个具体类型的指针之间进行转换
27     p3 = static_cast<float*>(0X2DF9);  //不能将整数转换为指针类型
28 
29     return 0;
30 }
View Code

 

const_cast关键字

将const类型转换为非const类型

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int main(){
 5     const int n = 100;
 6     int *p = const_cast<int*>(&n);
 7     *p = 234;
 8     cout<<"n = "<<n<<endl;
 9     cout<<"*p = "<<*p<<endl;
10 
11     return 0;
12 }

运行结果:

n = 100;

*p = 234;

&n用来获取 n 的地址,它的类型为const int *,必须使用 const_cast 转换为int *类型后才能赋值给 p。由于 p 指向了 n,并且 n 占用的是栈内存,有写入权限,所以可以通过 p 修改 n 的值。

有读者可能会问,为什么通过 n 和 *p 输出的值不一样呢?这是因为 C++ 对常量的处理更像是编译时期的#define,是一个值替换的过程,代码中所有使用 n 的地方在编译期间就被替换成了 100。换句话说,第 8 行代码被修改成了下面的形式:

cout<<"n = "<<100<<endl;

 

reinterpret_cast关键字

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class A{
 5 public:
 6     A(int a = 0, int b = 0): m_a(a), m_b(b){}
 7 private:
 8     int m_a;
 9     int m_b;
10 };
11 
12 int main(){
13     //将 char* 转换为 float*
14     char str[]="http://c.biancheng.net";
15     float *p1 = reinterpret_cast<float*>(str);
16     cout<<*p1<<endl;
17     //将 int 转换为 int*
18     int *p = reinterpret_cast<int*>(100);
19     //将 A* 转换为 int*
20     p = reinterpret_cast<int*>(new A(25, 96));
21     cout<<*p<<endl;
22    
23     return 0;
24 }
View Code

 

dynamic_cast关键字

dynamic_用于类的继承层次进行类型转换,允许向上转型,也允许向下转型。向上转型无检测,向下转型需经rtti进行检测,只有部分成功。

语法格式:

dynamic_cast<newType>(rxpression)

newType 和 expression 必须同时是指针类型或者引用类型。换句话说,dynamic_cast 只能转换指针类型和引用类型,其它类型(int、

double、数组、类、结构体等)都不行。

 

向上转型与向下转型

posted @ 2018-04-30 20:43  Hk_Mayfly  阅读(491)  评论(0编辑  收藏  举报