类型转换一:Type conversions One:

本文翻译自http://www.cplusplus.com/doc/tutorial/typecasting/

标准转换

short a=2000;
int b;
b=a;

short类型被自动提升为int.
标准准换影响基本数据类型。允许在数值间转换(shotr -> int , int -> float, double -> int …),数值和bool之间转换,以及一些指针转换。

更小的整数类型转为int,或者将float转为double,可以保证转换后的值与转换前的值是一样的。其它的算术间的转换并不总是能够表示相同的值。

int -> unsigned int : -1 变为最大的值。-2变为次最大的值(组成原理—-原反补码)。
数值类型0 <==> false; true –> 1, 非0 ->true。
float -> int:小数部分被去除。如果超过int可表示的范围,则转换导致未定义的行为(使用的字节长度int <= float <= double)。

有些转换可能意味着精度的损失,便一起可以发出警告,使用显示转换可以消除这种警告。

非数值类型转换,数组 & 函数 -> 指针。
通常的,指针支持如下转换:

  • Null指针 –> 任意类型指针
  • 指向任何类型的的指针 –> void指针
  • 指针向上转换: 派生类指针 –> 可被转换为可访问的没有异议的基类,无须修改const和volatile 限定(qualification).(不排除多重继承,不提倡多重继承,提倡接口。详细请看 Classes(IV) 类(四) の 继承 、 Classes(V) 类(五) 多态(Polymorphism). 注:这两篇文章种面没有提到多重继承)

类的隐式转换

隐式转换以来以下三个成员函数:
1. 构造函数:从一个特定类型的类A初始化对象B。
2. 赋值运算符:通过赋值将一种类型A赋值给B。
3. 类型转换操作符:隐式转换为特定类型。

#include <iostream>
using namespace std;

class A {};

class B {
public:
  // conversion from A (constructor):
  B (const A& x) {}
  // conversion from A (assignment):
  B& operator= (const A& x) {return *this;}
  // conversion to A (type-cast operator)
  operator A() {return A();}
};

int main ()
{
  A foo;
  B bar = foo;    // calls constructor
  bar = foo;      // calls assignment
  foo = bar;      // calls type-cast operator
  return 0;
}

类型转换: operator A(){}
A为目标类型

class A {} ;
class B { 
    operator A ()  { return A(); }
};

A a;    // 默认构造函数初始化a
B b;

a = b;  //B类型转换为A类型

注意B类中的函数A的形式 :operator + 目标类型A + 括号() + 函数体中 return A(), 没有返回值类型。

关键字显式

#include <iostream>
using namespace std;

class A {};

class B {
public:
  explicit B (const A& x) {}
  B& operator= (const A& x) {return *this;}
  operator A() {return A();}
};

void fn (B x) {}

int main ()
{
  A foo;
  B bar (foo);
  bar = foo;
  foo = bar;

// fn (foo); // not allowed for explicit ctor.
  fn (bar);  

  return 0;
}

在上面的代码中:

void fn (B x) {}

可以看到传入的参数为B类型的对象。
但是在类B中不难发现有个成员函数:

explicit B (const A& x) {}

可以将A类型的对象通过该构造函数转换为B类型,典型的可以通过

A foo;
B bar (foo)

的形式,该形式是调用接受一个参数的构造函数来初始化B类型对象bar。

但是在上面的void fn (B x){}函数中,
假如传入的参数时A类型,类B中的构造函数没有explicit关键字,会生成临时对象temp,该temp为B类型。这样,如果fn不是空的函数体,还有其它对传入类型敏感的操作,将会导致意外的效果。

所以:

  // fn (foo); // 是不被允许的,因为explicit关键字,与函数中指定的传入类型不匹配(A类型)
  fn (bar);  // 因为该类型正好是B类型。

而且,如果使用以下语句也是不备允许的:

A a;
B b = a;

你可能感兴趣的:(C++,类型转换)