我对C ++没有经验,但试图学习。
以下示例包含与"相关的":
的类层次结构MainClass.cpp:
#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;
}
WorkerClass.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;
};
Child.h
#include "Parent1.h"
#include "Parent2.h"
class Child : public Parent1, public Parent2
{
public:
Child(): Parent1(), Parent2() {}
~Child(){};
};
Parent1.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;
};
Parent2.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;
};
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 :所以我的主要问题是&#34; sideways&#34;从VirtualGrandParent转换为Parent1?为什么m_sister为0?内存被覆盖了吗? 为什么在m_sister为0之前需要两个方法调用?
问题2 :如果将地址带到WorkerClass.h中的指针ptr,然后将其转换为Parent1*
指针,会发生什么情况(下面的示例) )?使用此更改执行代码会导致m_sister未设置为0.我认为这只是一个巧合? (我猜指针指针确实应该是Parent1**
类型的?)
void setProperty1()
{
VirtualGrandParent* ptr = m_myMap[0];
((Parent1*) &ptr)->setProperty1(6.0);
}
答案 0 :(得分:2)
因此,如果我们将父母身份视为树:
VirtualGrandParent
\
Parent2 Parent1
\ /
Child
然后我们可以看到Parent1和VirtualGrandParent在不同的分支上。因此,当您将VirtualGrandParent* ptr
投射到Parent1
时,您没有正确地在层次结构中向上或向下投射。相反,它会跨越它而最终在不相关的类之间进行投射 - 这就是它产生无效结果的原因。
要沿着继承层次结构进行转换,请尝试始终至少使用static_cast
(或dynamic_cast
,如果需要)。使用static_cast
,编译器将验证转换是否至少是可能的,否则会出错。在您的情况下,它应该显示错误。
正确演员阵容为static_cast<Parent1*>(static_cast<Child*>(ptr))
至于你关于&ptr
的第二个问题......将指针指针作为指向类的指针只是无意义的。如果它看起来有用,那就是未定义行为的不幸运气。 (它可能实际上并没有正常工作,而是解释一些任意的内存,就好像它是你的类一样,然后碰巧有一个非零值,其中somePtr会以任何方式无效。)