Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当类型强制转换指针时会发生什么;“横向”;在C++; 我不是那么有经验的C++,而是想学。_C++_Polymorphism - Fatal编程技术网

当类型强制转换指针时会发生什么;“横向”;在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()

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

  • ChildParent1Parent2的孩子
  • Parent2VirtualGrandParent的子代
  • Parent2包含一个成员Sister*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;
}
工人阶级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