C++ 在三级继承的情况下,动态_cast会导致分段冲突
在三级继承的情况下,C++ 在三级继承的情况下,动态_cast会导致分段冲突,c++,inheritance,dynamic-cast,polymorphism,C++,Inheritance,Dynamic Cast,Polymorphism,在三级继承的情况下,dynamic\u cast似乎不起作用 应用程序在print()方法调用点(在main()中)由于分段错误(内核转储)而崩溃 代码如下: #include <iostream> #include <typeinfo> //must be included to call any member functions for the typeinfo object returned by typeid() using namespace std;
dynamic\u cast
似乎不起作用
应用程序在print()
方法调用点(在main()
中)由于分段错误(内核转储)而崩溃
代码如下:
#include <iostream>
#include <typeinfo> //must be included to call any member functions for the typeinfo object returned by typeid()
using namespace std;
class CBase
{
public:
virtual void print()
{
cout<<"CBase::print"<<endl;
}
virtual ~CBase()
{ }
};
class CDerivedA : public CBase
{
public:
virtual void print()
{
cout<<"CDerivedA::print"<<endl;
}
virtual ~CDerivedA()
{}
};
class CDerivedB : public CDerivedA
{
public:
void print()
{
cout<<"CDerivedB::print"<<endl;
}
};
int main()
{
CBase* ptrB = new CDerivedA();
CDerivedB* ptrDB = dynamic_cast<CDerivedB*>(ptrB);
ptrDB->print();
return 1;
}
#包括
#必须包含include//才能调用typeid()返回的typeinfo对象的任何成员函数
使用名称空间std;
C类数据库
{
公众:
虚拟空打印()
{
不能将指向CDerivedA(基类)的“指针”转换为“指向CDerivedB的指针”(派生类)。请注意,我指的不是声明的指针类型;问题是,指向的实际对象实际上是基类的一个实例,因此转换无法成功
dynamic_cast
在下行失败的情况下返回一个null
-指针,这可能是分段冲突的原因(在抛出引用的情况下,它将抛出一个bad_cast
异常)
请注意,dynamic\u cast
需要(运行时类型信息)才能正常工作。出于性能原因,可以在编译器中关闭RTTI(因为启用RTTI会在运行时带来一些开销)。请仔细检查编译器中是否启用了RTTI
编辑:关于您最后的评论-
下行广播的基础知识
不能向下转换基类的实例。可以向下转换声明为“指向基类的指针”的指针,该指针实际上指向派生类的实例。可以使用向下转换的示例如下:
class Base
{ public:
virtual void baseMethod() {cout<<"baseMethod in Base"<<endl;}
// I am omitting virtual destructors here for brevity,
// which you should _not_ do in your code!
}
class Derived : public Base
{ public:
void baseMethod() {cout<<"baseMethod in Derived"<<endl;}
virtual void derivedMethod(){cout<<"derivedMethod in Derived"<<endl;}
}
class Derived2 : public Derived
{ public:
void baseMethod() {cout<<"baseMethod in Derived2"<<endl;}
void derivedMethod(){cout<<"derivedMethod in Derived2"<<endl;}
void derived2Method(){cout<<"derived2Method in Derived2"<<endl;}
}
void someFunction(Base* pBase)
{
// pBase may actually point to an instance of Base, Derived or Derived2.
// But you can invoke only 'baseMethod' on pBase,
// since 'derivedMethod' and 'derived2Method' are not declared in Base.
pBase->baseMethod(); // ok
// ERROR: pBase->derivedMethod();
// ERROR: pBase->derived2Method();
// To invoke 'derivedMethod', you have to downcast to Derived:
Derived* pDerived = dynamic_cast<Derived*>(pBase);
if(pDerived /* != null */)
{
// Downcast successful, i.e.
// pBase actually points to an instance of Derived _or_ Derived2.
// Both have the 'derivedMethod', so you can invoke it via 'pDerived' pointer:
pDerived->derivedMethod(); // ok
// ERROR: pDerived->derived2Method();
// To call 'derived2Method', you have to downcast to Derived2.
}
else
{
// If we are here, then dynamic_cast returned null,
// i.e. the downcast was NOT successful
// and pBase actually points to an instance of Base.
}
}
我希望这有帮助
非常感谢您的更正。指向CDerivedA(基类)的“指针”不能转换为“指向CDerivedB的指针”(派生类)。请注意,我指的不是声明的指针类型;问题是指向的实际对象实际上是基类的实例,因此无法成功
dynamic_cast
在下行失败的情况下返回一个null
-指针,这可能是分段冲突的原因(在抛出引用的情况下,它将抛出一个bad_cast
异常)
请注意,dynamic\u cast
需要(运行时类型信息)才能正常工作。出于性能原因,可以在编译器中关闭RTTI(因为启用RTTI会在运行时带来一些开销)。请仔细检查编译器中是否启用了RTTI
编辑:关于您最后的评论-
下行广播的基础知识
不能向下转换基类的实例。可以向下转换声明为“指向基类的指针”的指针,该指针实际上指向派生类的实例。可以使用向下转换的示例如下:
class Base
{ public:
virtual void baseMethod() {cout<<"baseMethod in Base"<<endl;}
// I am omitting virtual destructors here for brevity,
// which you should _not_ do in your code!
}
class Derived : public Base
{ public:
void baseMethod() {cout<<"baseMethod in Derived"<<endl;}
virtual void derivedMethod(){cout<<"derivedMethod in Derived"<<endl;}
}
class Derived2 : public Derived
{ public:
void baseMethod() {cout<<"baseMethod in Derived2"<<endl;}
void derivedMethod(){cout<<"derivedMethod in Derived2"<<endl;}
void derived2Method(){cout<<"derived2Method in Derived2"<<endl;}
}
void someFunction(Base* pBase)
{
// pBase may actually point to an instance of Base, Derived or Derived2.
// But you can invoke only 'baseMethod' on pBase,
// since 'derivedMethod' and 'derived2Method' are not declared in Base.
pBase->baseMethod(); // ok
// ERROR: pBase->derivedMethod();
// ERROR: pBase->derived2Method();
// To invoke 'derivedMethod', you have to downcast to Derived:
Derived* pDerived = dynamic_cast<Derived*>(pBase);
if(pDerived /* != null */)
{
// Downcast successful, i.e.
// pBase actually points to an instance of Derived _or_ Derived2.
// Both have the 'derivedMethod', so you can invoke it via 'pDerived' pointer:
pDerived->derivedMethod(); // ok
// ERROR: pDerived->derived2Method();
// To call 'derived2Method', you have to downcast to Derived2.
}
else
{
// If we are here, then dynamic_cast returned null,
// i.e. the downcast was NOT successful
// and pBase actually points to an instance of Base.
}
}
我希望这有帮助
非常感谢您的更正。详细信息或没有发生。关于如何不在So上编写问题的完美示例显示您的代码,显示编译器错误消息…查看您的代码,我会说它工作正常,并且返回的NULL
与它应该的完全一致。您是否打算编写新CDerivedB
?@molbdnilo:不,我只是想了解对象的类型是否与基本指针(ptrB)相同要点必须是CDerivedB。它看起来更像是我们经常做的向下投射,但实际上有不同的事情。你认为在这个例子中向下投射是不可能的吗?详细信息还是没有发生。如何不在SOS上写问题的完美例子显示你的代码,显示编译器错误消息…看看你的代码,我会假设它正常工作,它返回的NULL
与它应该返回的完全一样。您是否打算编写new CDerivedB
?@molbdnilo:不,我只是想知道对象的类型是否与基指针(ptrB)相同要点必须是CDerivedB。它看起来更像是我们经常做的向下投射,但实际上有不同的事情。你认为在这个例子中向下投射是不可能的吗?@TadeuszKopec:当然,非常感谢!我更新了我的答案。看起来更像是我故意向下投射基类的一个实例。我阅读了最近在cplusplus中。这些语句真的让我困惑。对于动态\u转换(source\u pointer),source\u pointer的类型怎么可能是destination*的基类,大多数情况非常简单:检索源指针的RTTI信息,并获取类型destination*的RTTI信息。然后库例程确定源指针的类型是destination*类型还是destination*基类非常感谢你的好例子。所谓向下投射只是指从基类指向派生类的指针,实际上,指针指向的对象是“向上投射”的,因此它可以保证一个完整的对象。你同意吗?@yao:“向下投射只是指从基类指向派生类的指针”-确切地说,实际上,指针指向的对象没有任何改变。@:UpUp是从指针到派生类型到指针到基类的转换。这不需要显式的C++,例如:<代码>派生*P派生=新派生()。;Base*pBase=pDerived;
注意,指向的对象仍然是派生的的实例,它没有降级为Base
。升级总是安全的,而且总是成功的。@TadeuszKopec:当然,非常感谢!我已经更新了我的答案。看起来更像是我故意降级了基类的一个实例。当我阅读想想最近的cplusplus。这些语句真的让我困惑。对于动态的\u转换(source\u pointer),source\u指针的类型怎么可能是destination*的基类,大多数情况都非常简单:检索源指针的RTTI信息,获取类型destination*的RTTI信息