在C++中对指针进行类型转换"sideways"时会发生什么情况



我对C 的经验不是,而是尝试学习。

以下示例由"相关"类的层次结构组成:

  • 儿童 parent1 parent2
  • 的孩子
  • parent2 VirtualGrandParent 的孩子。
  • parent2 包含成员姐妹* m_sister ,它是另一个用户定义对象类型的指针。这是Parent2构造函数中的关键字 new 的初始化和分配的内存。在执行中的某个时刻,此指针设置为0。

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;
};

姐妹:

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的"侧向"铸造中会发生什么?为什么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);
}

,因此,如果我们将父母视为树:

VirtualGrandParent
       
      Parent2        Parent1
                   /
              Child

然后,我们可以看到Parent1和VirtualGrandParent在不同的分支上。因此,当您将VirtualGrandParent* ptr施放到Parent1时,您无法正确地铸造或下层次结构。相反

对于沿继承层次结构施放,请尝试始终使用至少static_cast(如果需要的话,或dynamic_cast)。使用static_cast,编译器将验证铸件至少可能是可能的,否则会出现错误。在您的情况下,应该显示错误。

适当的演员将是static_cast<Parent1*>(static_cast<Child*>(ptr))

至于您关于&ptr的第二个问题...将指针到A分量作为指针到A级的级别简直是胡说八道。如果看起来完全有效,那是不确定的行为的不幸运气。(而且它可能实际上不是正常工作的,而是解释一些任意内存,就好像是您的类一样,然后恰好具有非零的值,而某种程度上是某种程度上的,但在任何方面都不有效。)

相关内容

最新更新