1类型转换
1.1隐式类型转换
//隐式转换
char c='a';
int n=c;//基本类型的隐式转换
double d=97.243;
c1=d;
cout<<n<<c1<<endl;
1.2显式类型转换
//显示转换
int m=max(3,(int)3.14);//基本类型的强制转换
//但是不安全的所以在C++中有了4种强制转换
cout<<m<<endl;
2static_cast转换
用于非多态类型之间的转换,不提供运行时的检查来确保转换的安全性。
用法有以下
2.1基本数据类型转换
//int转换成char
int m1=max(3,static_cast<int>3.14);//优点 看起来明显 容易看见此处进行了强制类型转换
//int转换成enum
enum Week{
SUN,MON,TUE,WED,THU,FRI,SAT
};
Week day = 0;//error: invalid conversion from ‘int’ to ‘Week’
Week day = static_cast<Week>(0);//改正
2.2基类和子类之间指针和引用的转换
上行转换,把子类的指针或引用转换成父类,这种转换是安全的(通常使用默认转换)。
class Base{
public:
void Print(){cout << "Base" << endl;}
};
class Derive:public Base{
public:
void Print(){cout << "Derive" << endl;}
};
// 对象
Derive d;
Base b = static_cast<Base>(d);
b.Print();
// 引用
Base& fb = static_cast<Base&>(d);
fb.Print();
// 指针
Base* pb = static_cast<Base*>(new Derive);
pb->Print();
下行转换,把父类的指针或引用转换成子类,这种转换是不安全的, 也需要程序员来保证(通常使用dynamic_cast)。
2.3 指针/引用转换
void* pd = new Derive;
Base* pb = pd; // error: invalid conversion from ‘void*’ to ‘Base*’
Base* pb = static_cast<Base*>(pd);//正确写法
pb->Print();
3const_static
有以下作用
3.1主要作用是移除类型的const属性。
作用1:将const对象/指针/引用 转换为非const对象/指针/引用
作用2:在const成员函数中修改成员变量
class Test{
int n;
int count;//辅助成员 记录打印次数。
//也可以
mutable int count2;//mutable变量的意思是可变的 不受const影响
public:
Test(int n):n(n),cout(0){}
void Add(int m)const{
//本质是在const成员函数中This指针是const 所以this指针下的成员都是const
const_cast<int &>(n)+=m;
}
void Print()const{//assignment of member ‘Test::n’ in read-only object
//const函数不能修改成员变量
n+=m;
cout<<n<<endl;
++count;//increment of member ‘Test::count’ in read-only object
++const_cast<int&>count//改正写法 作用2:在const成员函数中修改成员变量
}
};
int main(){
//cosnt_cast<>()作用1:将const对象/指针/引用 转换为非const对象/指针/引用
const Test t(10);//const对象只能访问const函数
t.Print();
t.Add(5);//将‘const Test’作为‘void Test::Add(int)’的‘this’实参时丢弃了类型限定
const_cast<Test&>(t).Add(5);
t.Print();
}
3.2在const成员函数中修改成员变量的2种方法
class Test{
int n;
int count;//辅助成员 记录打印次数。
//方法1
mutable int count2;//mutable变量的意思是可变的 不受const影响
public:
Test(int n):n(n),cout(0){}
void Add(int m)const{
//本质是在const成员函数中This指针是const 所以this指针下的成员都是const
const_cast<int &>(n)+=m;
}
//方法2
void Print()const{//assignment of member ‘Test::n’ in read-only object
//const函数不能修改成员变量
n+=m;
cout<<n<<endl;
++count;//increment of member ‘Test::count’ in read-only object
++const_cast<int&>count//改正写法 作用2:在const成员函数中修改成员变量
}
};
4dynamic_cast(动态)
作用:用于类的指针、类的 引用 或者 void*转化。
主要用于以下三种情况:
上行转换,把子类的指针或引用转换成父类,与static_cast相同。
下行转换,把父类的指针或引用转换成子类,比static_cast安全。
交叉转换,兄弟之间指针转换,static_cast会出现编译错误。
4.1返回值
如果时指针,进行正确的转换,获得对应的值;否则返回NULL,如果是引用,则在运行时就会抛出异常
4.2下行转换
#include<iostream>
using namespace std;
class Base{
public:
void Func()const{
cout<<"Base::Func"<<endl;
}
virtual ~Base(){
}
};
class Derive:public Base{
public:
void Func()const{
cout<<"Derive::Func"<<endl;
}
~ Derive(){}
};
int main(){
//daynamic_cast 重要用在父子类中特别是指针
Derive d;
d.Func();//无多态
//结果root@foundation66 c++]# ./a.out //Derive::Func
Base *p=&d;
p->Func();//Base::Func 如果当父类的Func是虚函数
//使用p调用Derive
Derive *q=p;// 错误:从类型‘Base*’到类型‘Derive*’的转换无效
Derive *q=dynamic_cast<Derive>(p);//:无法将‘p’从类型‘Base*’动态转换到类型‘class Derive’(目标不是一个指针或引用)
//所以有个条件 父类任意成员函数必须要有一个是虚函数 通常都是析构函数
}
4.3交叉转换
#include <iostream>
using namespace std;
class Base {
public:
void Print() { cout << "Base" << endl; }
virtual ~Base(){}
};
class Derive1 : public Base {
public:
void Print() { cout << "Derive1" << endl; }
};
class Derive2 : public Base {
public:
void Print() { cout << "Derive" << endl; }
};
int main() { Derive1* pD1 = new Derive1;
pD1->Print();
//dynamic_cast只在多态有效。
Derive2 *pD2 = dynamic_cast<Derive2*>(pD1);
pD2->Print();
}
4.4条件
1:父类指针引用 转化成子类指针引用
2:父类指针指向子类对象
3:父类有虚函数 多态
5reinterpret_cast(重新解释)
修改了操作数类型,重新解释了给出的对象的比特模型而没有进行二进制转换。但危险系数高
主要用于以下六种情况:
1:从指针类型到一个足够大的整数类型
2:从整数类型或者枚举类型到指针类型
3:从一个指向函数的指针到另一个不同类型的指向函数的指针
4:从一个指向对象的指针到另一个不同类型的指向对象的指针
5:从一个指向类函数成员的指针到另一个指向不同类型的函数成员的指针
6:从一个指向类数据成员的指针到另一个指向不同类型的数据成员的指针
5.1指针类型与整数类型的转化
#include <iostream>
#include <vector>
using namespace std;
void Func(){
cout << "Func" << endl;
}
int main() {
// 变量指针类型与整数类型转化
{
int n = 100;
//把指针值(地址)转化成整数,
int addr = reinterpret_cast<int>(&n);
cout << "addr:" << hex << addr << dec << " "<< &n << endl;
//把整数转化成指针值。
int* b = reinterpret_cast<int*>(addr);
cout << "value:" << *b << endl;
}
// 函数指针类型与整数类型转化
{
int f = reinterpret_cast<int>(Func);
typedef void (*pFunc)();
pFunc pf = reinterpret_cast<pFunc>(f);
pf();
}
}
5.2函数指针的转化
#include <iostream>
#include <vector>
using namespace std;
void FuncNum(int n){
cout << "num:" << n << endl;
}
void FuncAddr(int* p) {
cout << "addr:" << p << endl;
}
int main() {
int n = 10;
FuncNum(n);
FuncAddr(&n);
typedef void (*pfNum)(int n);
typedef void (*pfAddr)(int* n);
pfNum pfunc = FuncNum;
pfunc(n);
reinterpret_cast<pfAddr>(pfunc)(&n);
}
5.3对象指针的转化
#include <iostream>
#include <vector>
using namespace std;
class A{
public:
void Func(){
cout << "A" << endl;
}
};
class B {
public:
void Test() { cout << "B" << endl; }
};
int main() {
A* pA = new A;
pA->Func();
B* pB = reinterpret_cast<B*>(pA);
pB->Test();
}
5.4类函数成员的转化
#include <iostream>
#include <vector>
using namespace std;
class A{
public:
void Func(){
cout << "A" << endl;
}
};
class B {
public:
void Test() { cout << "B" << endl; }
};
int main() {
// 对象的函数指针
{
A a;
a.Func();
typedef void (A::*Func_t)();
Func_t pfTest = reinterpret_cast<Func_t>(&B::Test);
(a.*pfTest)();
}
// 对象指针的函数指针
{
A *pA = new A;
pA->Func();
typedef void (A::*Func_t)();
Func_t pfTest = reinterpret_cast<Func_t>(&B::Test);
(pA->*pfTest)();
}
}
5.5类数据成员的转化
#include <iostream>
#include <vector>
using namespace std;
class Test{
public:
Test(int data) : data(data) {}
private:
int data;
};
int main() {
Test test(0x61626364);
char* p = reinterpret_cast<char*>(&test);
for (int i = 0; i != sizeof(Test) / sizeof(char); i++) {
cout << p[i] << endl;
}
}