Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.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++_Typechecking - Fatal编程技术网

C++ C++;将一个指针指定给另一个指针时执行的类型检查

C++ C++;将一个指针指定给另一个指针时执行的类型检查,c++,typechecking,C++,Typechecking,我想知道编译器在下面所做的类型检查的扩展 class Parent{ }; class Child : public Parent{ }; class Unrelated{ }; main(){ Parent* p = new Child() // OK. But type of p is still Parent* and not Child* Unrelatead* u = new Child() // Not OK. Child* is not Unrelated*. }

我想知道编译器在下面所做的类型检查的扩展

class Parent{
};

class Child : public Parent{
};

class Unrelated{
};

main(){
  Parent* p = new Child() // OK. But type of p is still Parent* and not Child*
  Unrelatead* u = new Child() // Not OK. Child* is not Unrelated*.
}
因此,在第一个赋值中,p现在指向子对象中的“父”对象,而第二个赋值是完全不允许的,尽管最终p和u都将保留内存地址


编译器在这些赋值过程中到底执行了哪些检查?编译器在编译的哪个部分执行这些检查?

编译器允许赋值数据指针:

  • 当两者都是指向同一类型的指针,或者目标指针是指向限制性更强的
    const
    /
    volatile
    限定类型的指针时,例如
    T*
    T const volatile*
  • 指向派生类的指针可以分配给指向具有类似或更严格的
    常量
    /
    volatile
    限定的可访问基类的指针,例如
    派生类*
    基类*
  • 任何指向
    void*
    的数据指针,具有类似或更严格的
    const
    /
    volatile
    限定,例如
    T const*
    void const*
  • Parent*p=newchild()编译,因为它是案例2


    unrelated*u=newchild()不编译,因为它不属于上述情况。要在不相关的数据指针之间进行赋值,需要重新解释转换。

    编译器允许赋值数据指针:

  • 当两者都是指向同一类型的指针,或者目标指针是指向限制性更强的
    const
    /
    volatile
    限定类型的指针时,例如
    T*
    T const volatile*
  • 指向派生类的指针可以分配给指向具有类似或更严格的
    常量
    /
    volatile
    限定的可访问基类的指针,例如
    派生类*
    基类*
  • 任何指向
    void*
    的数据指针,具有类似或更严格的
    const
    /
    volatile
    限定,例如
    T const*
    void const*
  • Parent*p=newchild()编译,因为它是案例2


    unrelated*u=newchild()不编译,因为它不属于上述情况。要使不相关数据指针之间的赋值有效,需要重新解释转换。

    第一个赋值是可以的,因为编译器将基类的所有内存安排在派生类的内存之前。 因此,您可以向上投射指针,因为基类的所有字段仍将被指向

    第二个赋值不正确,因为
    Child
    不是从
    unrelative
    继承的,因此它们的内存布局可能不同。 编译器跟踪这些类层次结构。 这些检查只在编译时发生

    请注意,向上投射指针可能是危险的。 如果您的类不是虚拟类,
    delete p
    将不会调用派生类的析构函数,从而导致潜在的内存泄漏。
    如果您决定向上转换并
    删除
    指针,请确保您是为虚拟类执行此操作。

    第一个赋值是可以的,因为编译器会将基类的所有内存安排在派生类的内存之前。 因此,您可以向上投射指针,因为基类的所有字段仍将被指向

    第二个赋值不正确,因为
    Child
    不是从
    unrelative
    继承的,因此它们的内存布局可能不同。 编译器跟踪这些类层次结构。 这些检查只在编译时发生

    请注意,向上投射指针可能是危险的。 如果您的类不是虚拟类,
    delete p
    将不会调用派生类的析构函数,从而导致潜在的内存泄漏。
    如果您决定向上转换并
    删除
    指针,请确保您是为虚拟类执行此操作。

    您所说的“这些检查在哪里”是什么意思?您所说的“编译器到底执行了哪些检查”是什么意思?这是一个简单的静态类型检查,不是吗?我的意思是基础数据将是内存地址(无符号长),那么编译器如何理解我不仅需要考虑这是无符号长的事实,但这也是一个指针,它指向的对象的类型是编译器执行与您在确定第一个赋值正确而第二个赋值不正确时执行的相同的精确检查。您所说的“这些检查在哪里”是什么意思?您所说的“编译器执行的确切检查是什么”是什么意思?这是一个简单的静态类型检查,不是吗?我的意思是基础数据将是内存地址(无符号长),那么编译器如何理解我不仅需要考虑这是无符号长的事实,但这也是一个指针,它指向的对象的类型是编译器执行与您在确定第一个赋值正确而第二个赋值不正确时执行的相同的精确检查。