指针内存表示和继承转换

时间:2017-12-07 18:40:55

标签: c++ pointers inheritance memory casting

当我注意到重新解释转换与向类型层次结构中较高的对象的指针向下转换为指向其基础类型的指针时,重新解释转换的效果与静态转换一样。

我的言语不太好,所以要看看我想说的话,请考虑以下代码:

#include <iostream>
#include <string>

class A {
public:
  A (void) {
  }
  virtual ~A (void) noexcept {
  }
  virtual void ABehaviour (void) const {
    std::cout << "Behaviour of Object A implemented in Object A.\n";
  } 
};

class B : public A {
public:  
  B (void) 
    : A () {
  }
  ~B (void) noexcept override {
  }
  void ABehaviour (void) const override {
    std::cout << "Behaviour of Object A implemented in Object B.\n";
  }
  void BBehaviour (void) const {
    std::cout << "Behaviour of Object B implemented in Object B.\n";
  }
};

int main (int arg_count, char* arg_vector[]) {
  B* b_object1 = new B (); // Create an object B.
  b_object1->ABehaviour (); // This line works fine.
  b_object1->BBehaviour (); // This line works fine.

  A* a_object1 = b_object1 // Implicit Upcast to Object A.
  a_object1->ABehaviour (); // This line works fine.
  a_object1->BBehaviour (); // This is a compile time error.

  B* b_object2 = reinterinpret_cast <B*> (a_object1);
  b_object2->ABehaviour (); // This line works fine.
  b_object2->BBehaviour (); // This line works fine.

  delete b_object1;
  b_object1 = nullptr;
  a_object1 = nullptr;
  b_object2 = nullptr;

  return 0;
}

直观地说,上面的演员应该有效,因为它类似于调用:

B* b_object2 = static_cast <B*> (static_cast <void*> (a_object1));

从我所读过的内容来看,reinterpret_cast是一个编译器指令,它告诉编译器将对象被转换的位序列解释为被转换为&的对象的一系列位。 #39; S。在上述情况下,A *被重新解释为B *。

从很久以前我在C ++中学习入门课程时我所理解的是,指针本身就是包含其他变量地址的变量。因此,当执行上述重新解释转换时,编译器被告知将指针解释为A的比特序列,就好像它是指向B的比特序列(不是它们的内容本身)的指针。 / p>

所以我的问题是,我的直觉是正确的,还是指针在内部工作时有点不同。如果我错了,任何人都会关心如何将指针存储在内存中以及它们的内部如何在内部工作(包括向上和向下)?

对于文字墙感到抱歉,并提前谢谢你们!

1 个答案:

答案 0 :(得分:0)

a_object1是一个指向A类型对象的指针。所以它只能访问A的方法。

您对指针的理解也是正确的。指针只保存它指向的对象的地址。因此指针本身没有类型。当我说A类型的指针时,我指的是指向A(或A的子类)的指针。

A* a_object1 = b_object1与执行static_cast<A*> (b_object1)相同。

如果您想要致电BBehaviour() a_object1,则必须执行static_cast<B*>(a_object1)->BBehaviour()。在这种情况下它会起作用,因为尽管a_object1的类型为A*,但它指向具有运行时类型B*的对象。

static_cast<B*>(a_object1)->BBehaviour()这样的代码是BTW设计糟糕的标志,所以你要避免这种情况。 (如果你需要这样做,你可以在这里使用dynamic_cast。)

另一方面,

reinterpret_cast<>()可以将任何对象更改为任何其他不相关的对象。例如:

std::string str = reinterpret_cast<std::string>(a_object1)

编译正常,但运行时会遇到问题。