dynamic_cast 和多态性
dynamic_cast and polymorphism
这是我在这个网站上的第一个问题,所以请随时强调我的用词选择、问题结构等方面的任何问题。
最近,我在处理多态性时开始使用 dynamic_cast
,我读到 dynamic_cast
不会创建 class 的另一个实例,而是创建另一个对象指针的实例。
在测试dynamic_cast
时遇到了这个问题。这是代码:
//main.cpp
#include <iostream>
class Base{
public:
int BaseNum;
virtual void BaseFunction(){};
};
class Derived : public Base{
public:
int DerivedNum;
virtual void DerivedFunction(){};
};
int main(){
Base * ptrBase = new Base;
ptrBase->BaseNum = 0;
Derived * ptrDerived = dynamic_cast<Derived *>(ptrBase);
ptrDerived->DerivedNum = 1;
std::cout << ptrBase->BaseNum << ptrDerived->DerivedNum << std::endl;
system("pause");
return 0;
}
程序崩溃行:
ptrDerived->DerivedNum = 1;
调试时显示"unable to read memory"。我的结论是,如果原始内存分配是为层次结构中更高的 class 保留的,我不能沮丧,但我认为我可能错了。
代码哪里出错了?
您的问题是您正在向后使用动态转换。
如果你这样做了
Base *ptrBase = new Derived ;
那就可以了。
派生是一个基础。
基础不是派生的。
dynamic_cast
在指定对象中找到请求的 class 类型,并且 return 将 pointer/reference 定位到对象的该部分。如果找不到,则为指针转换 return 编辑 NULL,并为引用转换抛出 std::bad_cast
异常。在您的示例中,它失败了,因为 ptrBase
未指向作为 Derived
class 实例的对象,因此对象中没有 Derived
部分 return 指向的指针,因此它 return 为 NULL。你需要改变这个:
Base * ptrBase = new Base;
改为:
Base * ptrBase = new Derived;
在您的示例代码中,您创建了 Base
的新实例:
Base * ptrBase = new Base;
ptrBase->BaseNum = 0;
Derived * ptrDerived = dynamic_cast<Derived *>(ptrBase);
由于 Derived
是 Base
的超集,但 base 只是 Derived
的子集,您不能将 ptrBase
指向的对象作为 Derived
,因为它比 Derived
.
'smaller'
另一方面,如果您写
Base * ptrBase = new Derived;
ptrBase->BaseNum = 0;
Derived * ptrDerived = dynamic_cast<Derived *>(ptrBase);
那么一切都很好,因为现在ptrBase
指向的对象是Derived
.
使用dynamic_cast
,由程序员来确保转换成功。
这是我在这个网站上的第一个问题,所以请随时强调我的用词选择、问题结构等方面的任何问题。
最近,我在处理多态性时开始使用 dynamic_cast
,我读到 dynamic_cast
不会创建 class 的另一个实例,而是创建另一个对象指针的实例。
在测试dynamic_cast
时遇到了这个问题。这是代码:
//main.cpp
#include <iostream>
class Base{
public:
int BaseNum;
virtual void BaseFunction(){};
};
class Derived : public Base{
public:
int DerivedNum;
virtual void DerivedFunction(){};
};
int main(){
Base * ptrBase = new Base;
ptrBase->BaseNum = 0;
Derived * ptrDerived = dynamic_cast<Derived *>(ptrBase);
ptrDerived->DerivedNum = 1;
std::cout << ptrBase->BaseNum << ptrDerived->DerivedNum << std::endl;
system("pause");
return 0;
}
程序崩溃行:
ptrDerived->DerivedNum = 1;
调试时显示"unable to read memory"。我的结论是,如果原始内存分配是为层次结构中更高的 class 保留的,我不能沮丧,但我认为我可能错了。
代码哪里出错了?
您的问题是您正在向后使用动态转换。
如果你这样做了
Base *ptrBase = new Derived ;
那就可以了。
派生是一个基础。 基础不是派生的。
dynamic_cast
在指定对象中找到请求的 class 类型,并且 return 将 pointer/reference 定位到对象的该部分。如果找不到,则为指针转换 return 编辑 NULL,并为引用转换抛出 std::bad_cast
异常。在您的示例中,它失败了,因为 ptrBase
未指向作为 Derived
class 实例的对象,因此对象中没有 Derived
部分 return 指向的指针,因此它 return 为 NULL。你需要改变这个:
Base * ptrBase = new Base;
改为:
Base * ptrBase = new Derived;
在您的示例代码中,您创建了 Base
的新实例:
Base * ptrBase = new Base;
ptrBase->BaseNum = 0;
Derived * ptrDerived = dynamic_cast<Derived *>(ptrBase);
由于 Derived
是 Base
的超集,但 base 只是 Derived
的子集,您不能将 ptrBase
指向的对象作为 Derived
,因为它比 Derived
.
另一方面,如果您写
Base * ptrBase = new Derived;
ptrBase->BaseNum = 0;
Derived * ptrDerived = dynamic_cast<Derived *>(ptrBase);
那么一切都很好,因为现在ptrBase
指向的对象是Derived
.
使用dynamic_cast
,由程序员来确保转换成功。