当类型强制转换指针时会发生什么;“横向”;在C++; 我不是那么有经验的C++,而是想学。
以下示例由“相关”类的层次结构组成:当类型强制转换指针时会发生什么;“横向”;在C++; 我不是那么有经验的C++,而是想学。,c++,polymorphism,C++,Polymorphism,以下示例由“相关”类的层次结构组成: Child是Parent1和Parent2的孩子 Parent2是VirtualGrandParent的子代 Parent2包含一个成员Sister*m_Sister,该成员是指向另一个用户定义对象类型的指针。在Parent2的构造函数中使用关键字new初始化并分配内存。在执行过程中的某个时刻,该指针被设置为0 MainClass.cpp: #include "WorkerClass.h" using namespace std; int main()
- Child是Parent1和Parent2的孩子
- Parent2是VirtualGrandParent的子代
- Parent2包含一个成员Sister*m_Sister,该成员是指向另一个用户定义对象类型的指针。在Parent2的构造函数中使用关键字new初始化并分配内存。在执行过程中的某个时刻,该指针被设置为0
#include "WorkerClass.h"
using namespace std;
int main()
{
WorkerClass worker;
worker.initialize();
worker.setProperty1();
worker.setProperty2();
// At this point m_sister (in Parent2) is set to 0x0, which makes the next method call fail (Segmentation fault). What happens?
worker.setAuntValue();
return 0;
}
工人阶级h:
#include <map>
#include "Child.h"
class WorkerClass
{
public:
void initialize()
{
Child* child1 = new Child();
m_myMap[0] = child1;
}
void setProperty1()
{
VirtualGrandParent* ptr = m_myMap[0];
((Parent1*) ptr)->setProperty1(6.0);
}
void setProperty2()
{
VirtualGrandParent* ptr = m_myMap[0];
((Parent1*) ptr)->setProperty2(7.0);
}
void setAuntValue()
{
VirtualGrandParent* ptr = m_myMap[0];
((Child*) ptr)->setSisterValue(170.0);
}
private:
map<int, VirtualGrandParent*> m_myMap;
};
家长1.h:
class Parent1
{
public:
Parent1(): m_value1(0.0), m_value2(0.0) {}
virtual ~Parent1() {};
void setProperty1(double val) {m_value1=val;}
void setProperty2(double val) {m_value2=val;}
private:
double m_value1;
double m_value2;
};
父母2.h:
#include "Sister.h"
#include "VirtualGrandParent.h"
class Parent2 : public VirtualGrandParent
{
public:
Parent2(): VirtualGrandParent() {m_sister = new Sister();}
~Parent2(){};
void setSisterValue(double val){m_sister->setValue(val);}
protected:
Sister* m_sister;
};
h修女:
class Sister {
public:
Sister(): m_sisterVal(0.0) {};
void setValue(double val)
{
m_sisterVal=val;
}
private:
double m_sisterVal;
};
VirtualGrandParent.h:
class VirtualGrandParent
{
public:
VirtualGrandParent() {}
virtual ~VirtualGrandParent(){};
};
问题1:那么我的主要问题是,在从VirtualGrandParent到Parent1的“横向”铸造过程中会发生什么?为什么你的妹妹是0?内存被覆盖了吗?
为什么在m_sister为0之前需要两个方法调用
问题2:如果将地址转移到WorkerClass.h中的指针ptr,然后将其转换为Parent1*
指针(下面的示例),会发生什么情况?使用此更改执行代码会导致m_sister未设置为0。我想这只是巧合吧?(我想指向指针的指针应该是Parent1**
?)
因此,如果我们将亲子关系视为一棵树:
VirtualGrandParent
\
Parent2 Parent1
\ /
Child
然后我们可以看到Parent1和VirtualGrandParent位于不同的分支上。因此,当您将VirtualGrandParent*ptr
转换为Parent1
时,您没有正确地向上或向下转换层次结构。取而代之的是在它之间进行强制转换,最终在不相关的类之间进行强制转换——这就是它产生无效结果的原因
要沿继承层次结构进行强制转换,请尝试始终至少使用静态强制转换
(或动态强制转换
,如果需要)。使用静态\u转换
编译器将验证转换至少是可能的,否则将给出错误。在您的情况下,它应该显示一个错误
正确的强制转换应该是static\u cast(static\u cast(ptr))
关于
&ptr
的第二个问题。。。将指向a的指针转换为指向a类的指针简直是胡说八道。如果它看起来真的有效,那就是未定义行为的不幸运气。(它可能实际上工作不正常,而是将一些任意内存解释为您的类,然后正好有一个非零值,其中somePtr可能是但无论如何都无效。)因此,如果我们将父级视为一棵树:
VirtualGrandParent
\
Parent2 Parent1
\ /
Child
然后我们可以看到Parent1和VirtualGrandParent位于不同的分支上。因此,当您将VirtualGrandParent*ptr
转换为Parent1
时,您没有正确地向上或向下转换层次结构。取而代之的是在它之间进行强制转换,最终在不相关的类之间进行强制转换——这就是它产生无效结果的原因
要沿继承层次结构进行强制转换,请尝试始终至少使用静态强制转换
(或动态强制转换
,如果需要)。使用静态\u转换
编译器将验证转换至少是可能的,否则将给出错误。在您的情况下,它应该显示一个错误
正确的强制转换应该是static\u cast(static\u cast(ptr))
关于
&ptr
的第二个问题。。。将指向a的指针转换为指向a类的指针简直是胡说八道。如果它看起来真的有效,那就是未定义行为的不幸运气。(它可能实际上工作不正常,而是像解释你的类一样解释一些任意内存,然后正好有一个非零值,其中somePtr可能是,但无论如何都无效。)我建议你重新表述这个问题,并实际添加一个完整的示例来说明这个问题。我们这里没有人有你的代码来理解你模糊的描述的确切含义。好的,我现在试着提供一个例子。希望这更有意义。当我运行这个例子时,我得到了分段错误(空指针)。这真的是解决这个问题的最好方法吗?它重现了这个问题。。。太大了吗?我可以尝试删除一些内容,但仍然看到相同的错误…VirtualGrandParent
包含一个虚拟析构函数和一个指针(m_sister
),而Parent1
包含一个虚拟析构函数和两个双精度。因此,当你将前者的一个实例解释为后者的一个实例时,你的指针m_sister
位于你假设第一个双精度的位置,因此在向该双精度写入时,你实际上改变了指针。我建议你重新表述这个问题,并实际添加一个完整的示例来说明这个问题。我们这里没有人有你的代码来理解你模糊的描述的确切含义。好的,我现在试着提供一个例子。希望这更有意义。当我运行这个例子时,我得到了分段错误(空指针)。这真的是解决这个问题的最好方法吗?它重现了这个问题。。。太大了吗?我可以尝试删除一些内容,但仍然看到相同的错误…VirtualGrandParent
包含一个虚拟析构函数和一个指针(m_sister
),而Parent1
包含一个虚拟析构函数和两个双精度。因此,当您将前一个实例解释为后一个实例时,您的指针m_sister
位于假定第一个双精度的位置,因此在写入该双精度时,您实际上更改了指针代码>现在就可以了;Parent2的指针不再设置为0。因此,从VirtualGrandParent到Parent1的强制转换实际上是可能的,但必须分两步完成(从VirtualGrandParent到Child,然后从Child到Parent1),并且必须使用static\u cast
?@Hippo两步完成
VirtualGrandParent
\
Parent2 Parent1
\ /
Child