一.基类和派生类的裸指针转换
- 派生类的地址或者指针赋值给基类指针时,一般都用隐式转换。(也可以使用static_cast、dynamic_cast显示转换)
反过来,
#include <iostream>
class base
{
public:
virtual ~base(void) = default;
};
class derived :public base
{
};
int main()
{
derived derivedobj;
std::cout << "派生类对象的地址是:" << &derivedobj << std::endl;
base *pointer1 = &derivedobj;
std::cout << "隐式转换后,基类裸指针保存的地址是:" << pointer1 << std::endl;
base *pointer2 = static_cast<base *>(&derivedobj);
std::cout << "static_cast转换后,基类裸指针保存的地址是:" << pointer2 << std::endl;
derived *pointer4 = dynamic_cast<derived *>(pointer1);
std::cout << "dynamic_cast转换后,派生类裸指针保存的地址是:" << pointer4 << std::endl;
derived *pointer5 = static_cast<derived *>(pointer1);
std::cout << "static_cast转换后,派生类裸指针保存的地址是:" << pointer5 << std::endl;
return 0;
}
派生类对象的地址是:003AFA0C 隐式转换后,基类裸指针保存的地址是:003AFA0C static_cast转换后,基类裸指针保存的地址是:003AFA0C dynamic_cast转换后,派生类裸指针保存的地址是:003AFA0C static_cast转换后,派生类裸指针保存的地址是:003AFA0C
二.dynamic_cast和static_cast的区别
1、对于有继承关系的两个类:
- (1)子类转成父类dynamic_cast和static_cast都没有问题.
- (2)父类转成子类,dynamic_cast要求父类中有虚函数,否则编译不通过。static_cast不作此要求,编译通过。
在有虚函数的前提下,如果父类指针的确实指向的是子类实例,dynamic_cast转换成功,否则返回NULL; static_cast对于转换前的指针是否指向实际子类实例,不作要求,都能转换成功。 - (3)在编译通过成功,且返回指针不为空的前提下,两者转换结果指针,都可以用来读写父类和子类成员函数和变量。
- (4)如果父类指针不是指向子类实例,编译都能通过,但是dynamic_cast返回为NULL,不能操作对象;
static_cast返回非空指针,可以读写父类成员变量,也能调用其成员函数。子类的成员函数可以调用,但是当操作涉及子类成员变量时候,不成功。
2、对于没有继承关系的两个类
static_cast可以编译通过,dynamic_cast不能编译通过。两者都不能读写成员变量和函数。
3、demo(即二.1.(4))
#include <iostream>
class base
{
public:
virtual ~base(void) = default;
};
class derived :public base
{
public:
int a=0;
};
class test : public base
{
};
int main()
{
std::cout << std::boolalpha;
derived derivedobj;
test testobj;
base *pointer = &derivedobj;
test *pointer2 = dynamic_cast<test *>(pointer);
std::cout << "test指针保存derivedobj的地址(dynamic_cast):" << std::endl;
std::cout << "是否成功:" << (pointer2 != nullptr) << std::endl << std::endl;
test *pointer4 = static_cast<test *>(pointer);
std::cout << "test指针保存derivedobj的地址(static_cast):" << std::endl;
std::cout << "是否成功:" << (pointer4 != nullptr) << std::endl << std::endl;
return 0;
}
输出结果
test指针保存derivedobj的地址(dynamic_cast): 是否成功:false
链接: dynamic_cast和static_cast的异同.
三.dynamic_cast 转换引用
- dynamic_cast转换指针时,转换失败可以通过nullptr来表达。
- 而引用就不能。所以dynamic_cast转换引用使用的是抛出异常std::bad_cast。std::bad_cast在标准库typeinfo中。
#include <iostream>
#include <typeinfo>
class base
{
public:
virtual ~base(void) = default;
};
class derived : public base
{
};
class test : public base
{
};
int main(void)
try
{
std::cout << std::boolalpha;
derived derivedobj;
test testobj;
base &object = derivedobj;
derived &ref1 = dynamic_cast<derived &>(object);
std::cout << "成功转换成derived引用" << std::endl;
test &ref2 = dynamic_cast<test &>(object);
std::cout << "成功转换成test引用" << std::endl;
return 0;
}
catch (const std::bad_cast &)
{
std::cout << "转换失败" << std::endl;
}
四.基类和派生类的智能指针转换
- 基类和派生类的智能指针转换要使用std::dynamic_pointer_cast和std::static_pointer_cast。
- (std::dynamic_pointer_cast和dynamic_cast原理一样,std::static_pointer_cast和static_cast原理一样。)
参考 1.基类和派生类相互转换.
|