·  阅读 152

# Summary

www.cplusplus.com/doc/tutoria…

# Implicit conversion 隐式转换

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

# Implicit conversions with classes 类的隐式转换

• 单参数构造函数： 允许从特定类型进行隐式转换以初始化对象。
• 赋值运算符： 允许在赋值时从特定类型进行隐式转换。
• 类型转换运算符： 允许隐式转换为特定类型。
``````// implicit conversion of classes:
#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;
}

# Keyword explicit 显式关键字

``````// explicit:
#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;
}

# Type casting 类型转换

C++ 是一种强类型语言。许多转换，特别是那些暗示对值有不同解释的转换，需要显式转换，在 C++ 中称为type-casting。泛型类型转换有两种主要语法：`functional notation``c-like cast notation`

``````double x = 10.3;
int y;
y = int (x);    // functional notation
y = (int) x;    // c-like cast notation

``````// class type-casting
#include <iostream>
using namespace std;

class Dummy {
double i,j;
};

int x,y;
public:
Addition (int a, int b) { x=a; y=b; }
int result() { return x+y;}
};

int main () {
Dummy d;
return 0;
}

dynamic_cast <new_type> (expression)
reinterpret_cast <new_type> (expression)
static_cast <new_type> (expression)
const_cast <new_type> (expression)

## dynamic_cast

dynamic_cast 只能够用在指向类的指针或者引用上(或者void*)。这种转换的目的是确保目标指针类型所指向的是一个有效且完整的对象。

dynamic_cast 也能downcast(从基类向派生类的转换)当且仅当转过去的指针所指向的目标对象有效且完整。例如:

``````// dynamic_cast
#include <iostream>
#include <exception>
using namespace std;

class Base { virtual void dummy() {} };
class Derived: public Base { int a; };

int main () {
try {
Base * pba = new Derived;
Base * pbb = new Base;
Derived * pd;

pd = dynamic_cast<Derived*>(pba);
if (pd==0) cout << "Null pointer on first type-cast.\n";

pd = dynamic_cast<Derived*>(pbb);
if (pd==0) cout << "Null pointer on second type-cast.\n";

} catch (exception& e) {cout << "Exception: " << e.what();}
return 0;
}

``````Null pointer on second type-cast.

## static_cast

static_cast能够完成指向相关类的指针上的转换。upcast和downcast都能够支持，但不同的是，并不会有运行时的检查来确保转换到目标类型上的指针所指向的对象有效且完整。因此，这就完全依赖程序员来确保转换的安全性。但反过来说，这也不会带来额外检查的开销。例如

``````class Base {};
class Derived: public Base {};
Base * a = new Base;
Derived * b = static_cast<Derived*>(a);

• void*转向任何指针类型；假如该指针是从某指针类型上转到void *，现在再次转到相同的指针类型上去的话，保证转换后的指针本身的值不变。
• 整数，浮点以及枚举类型向枚举类型的转换。

• 显式调用仅有一个参数的构造函数或者是转换操作符(conversion operator)
• 转换到右值引用
• 枚举类的值向整数或浮点的转换
• 任意类型向void的转换，目标值在被求值之后舍弃。

## reinterpret_cast

reinterpret_cast能够完成任意指针类型向任意指针类型的转换，即使它们毫无关联。该转换的操作结果是出现一份完全相同的二进制复制品，既不会有指向内容的检查，也不会有指针本身类型的检查。

reinterpret_cast也能够完成指针向整数的转换。不过该整数的类型取决于平台。唯一的保证是该整数的类型能够容纳下指针的值以及能够再次被转换成一个有效的指针。

``````class A { /* ... */ };
class B { /* ... */ };
A * a = new A;
B * b = reinterpret_cast<B*>(a);

## const_cast

const_cast可以用来设置或者移除指针所指向对象的const。例如，要把一个const指针传入一个接受非const指针的函数里:

``````// const_cast
#include <iostream>
using namespace std;

void print (char * str)
{
cout << str << '\n';
}

int main () {
const char * c = "sample text";
print ( const_cast<char *> (c) );
return 0;
}

``````sample text

# typeid

typeid用来检查表达式的类型。

``````typeid (expression)

``````// typeid
#include <iostream>
#include <typeinfo>
using namespace std;

int main () {
int * a,b;
a=0; b=0;
if (typeid(a) != typeid(b))
{
cout << "a and b are of different types:\n";
cout << "a is: " << typeid(a).name() << '\n';
cout << "b is: " << typeid(b).name() << '\n';
}
return 0;
}

``````a and b are of different types:
a is: int *
b is: int

``````// typeid, polymorphic class
#include <iostream>
#include <typeinfo>
#include <exception>
using namespace std;

class Base { virtual void f(){} };
class Derived : public Base {};

int main () {
try {
Base* a = new Base;
Base* b = new Derived;
cout << "a is: " << typeid(a).name() << '\n';
cout << "b is: " << typeid(b).name() << '\n';
cout << "*a is: " << typeid(*a).name() << '\n';
cout << "*b is: " << typeid(*b).name() << '\n';
} catch (exception& e) { cout << "Exception: " << e.what() << '\n'; }
return 0;
}

``````a is: class Base *
b is: class Base *
*a is: class Base
*b is: class Derived