类的转换
类的转换包括:隐式转换和显式转换
(1)隐式转换
将一个类对象的类型转为另一种类类型。如果一个类定义了转换构造函数或者转换运算符,那么编译器可以自动执行隐式转换
class B
{
public:
double dVal;
public:
B(double dVal_) : dVal(dVal_) {}
B(int iVal_) :dVal(iVal_) {}
};
class A
{
public:
int iVal;
public:
A() {};
A(int iVal_) : iVal(iVal_) {}
A(B bObj)
{
iVal = (int)bObj.dVal;
}
};
void main()
{
B bObj(3.14);
A aObj=bObj; //隐式地调用A的转换构造函数,将B转换成A
std::cout << aObj.iVal << std::endl; //打印:3
}
上述代码类A和类B都定义了转换构造函数,在实际使用的时候,可以自动进行隐式转换(类型转换)
(2)禁止隐式转换
explicit A(B bObj){...}
将A的转换构造函数使用关键字explicit进行修饰之后,A aObj = bObj;将会报错,这个时候必须使用显式类型转换,实现类B对象向类A对象的转换
(3)显式转换
使用显式转换操作符 static_cast、dynamic_cast、reinterpret_cast 和 const_cast 来实现不 同类型之间的转换
A.static_cast
- 用于基本的类型转换、类层次结构间的上行转换(派生类指针向基类指针的转换)
和下行转换(基类指针向派生类指针的转换) - 在编译时进行类型检查,不提供运行时类型检查:
- 编译时类型检查:编译时编译器会检查代码中的类型错误和不一致之处,并给出 相应警告或提示。这种类型检查主要发生在编译阶段,在生成可执行文件之前
- 运行时类型检查:程序运行时根据对象的实际类型检查和处理类型相关的问题
- 在执行向上转型和向下转型时不提供动态检查,因此不安全
// static_cast 向下转换 01:指向派生类对象
Base *base_ptr = new Drived(0, 01);
base_ptr->showInfo(); // (静态绑定)打印:BaseClass! 0
base_ptr->virtual_showInfo(); // (动态绑定)打印:virtual method in DrivedClass! 1
Drived *drived_ptr = static_cast<Drived *>(base_ptr);
drived_ptr->showInfo(); // 打印:DrivedClass! 1
drived_ptr->virtual_showInfo(); // 打印:virtual method in DrivedClass! 1
cout << "*****************************" << endl;
// static_cast 向下转换 02:不指向派生类对象,这样转没有意义,属于非法转换
Base *base_ptr01 = new Base(1);
Drived *drive_ptr01 = static_cast<Drived *>(base_ptr01);
drive_ptr01->showInfo(); // 打印:DrivedClass! -1163005939
drive_ptr01->virtual_showInfo(); // 打印:virsual method in BaseClass! 1
cout << "*****************************" << endl;
// static_cast 向上转换
Drived *drive_ptr02 = new Drived(2, 22);
drive_ptr02->showInfo(); // 打印:DrivedClass! 22
drive_ptr02->virtual_showInfo(); // 打印:virtual method in DrivedClass! 22
Base *base_ptr02 = static_cast<Base *>(drive_ptr02);
base_ptr02->showInfo(); // 打印:BaseClass! 2
base_ptr02->virtual_showInfo(); // (动态绑定)打印:virtual method in DrivedClass! 22
cout << "*****************************" << endl;
B.dynamic_cast
- 用于类层次结构间的安全向下转换:基类强转为派生类(父类强转为子类)
- 运行时类型检查,可以检查是否进行有效的类型转换
- 要确保基类指针或引用实际上指向派生类对象,如果转换不可行,则返回空指针(对指针进行转换)或抛出 std::bad_cast 异常(对引用进行转换)
- 只能用于含有虚函数的类
// dynami_cast 向下转换 01:不指向派生类
Base *base_ptr03 = new Base(3);
// 要求基类指针指向的实际对象是派生类的对象。否则,转换将失败并返回空指针
Drived *drive_ptr03 = dynamic_cast<Drived *>(base_ptr03);
if (drive_ptr03){
drive_ptr03->showInfo();
drive_ptr03->virtual_showInfo();
}
else
cout << "转换失败!" << endl; // 打印:转换失败!
cout << "*****************************" << endl;
// dynami_cast 向下转换 02:指向派生类
Base *base_ptr04 = new Drived(4, 44);
Drived *drive_ptr04 = dynamic_cast<Drived *>(base_ptr04);
drive_ptr04->showInfo(); // 打印:DrivedClass! 44
drive_ptr04->virtual_showInfo(); // 打印:virtual method in DrivedClass! 44
C.reinterpret_cast
- 不进行类型检查或安全性检查,完全依赖于程序员自己来确保类型转换的正确性
- 用于指针或引用之间的类型转换,也可用于不同类型之间的转换,如将整型转换为指针类型。
- 执行非常低级的转换,可能会导致未定义行为。
D.const_cast
- 添加 const 属性:给常规变量、指针或引用添加 const 属性
- 删除 const 属性:去除常规常量、顶层指针和引用的 const 属性
- 不要修改去除了 const 的 nonConstValue 变量,因为其行为是未定义的
- const_cast 去除 const 属性主要作用是赋值和用作函数参数传递,避免重载带有 const参数的函数