【问题标题】:C++, what does pointer really mean? when virtual involvedC++,指针的真正含义是什么?当涉及虚拟时
【发布时间】:2012-09-26 01:12:37
【问题描述】:

如下代码

class A 
{
public:
    ~A()
    {
        std::cout << "a"  << std::endl;
    }
};

class B : public A {
public:
    virtual ~B()
    {
        std::cout << "b"  << std::endl;
    }
};

int main()
{
    B* b = new B();
    A* a = b;

    if (a == b)
    {

    }

    delete a;
}

问题是,“a”是否等于“b”?这是为什么以及如何发生的? 指针的真正含义是什么?不只是地址和内存块的长度?

【问题讨论】:

  • 是的,a 指向的地址将等于b 指向的地址,除非涉及到多重继承。然后 C++ 就变得奇怪了……
  • b指向的对象是B,但也是A。所以指向A 对象的指针可以指向b,因为*bA
  • 您的代码有未定义的行为。您正在通过基类A * 删除B 对象,但A 的析构函数不是virtual

标签: c++ pointers virtual


【解决方案1】:

“a”会等于“b”吗?

是的

为什么以及如何发生这种情况?

为了执行两个指针的比较,编译器将执行到通用类型的转换。在这种情况下,由于AB 的基数,因此转换为A*,产生的代码相当于:

A* __tmp = b;
if ( a == __tmp ) ...

指针的真正含义是什么?不只是地址和内存块的长度?

指针是保存对象地址的变量(指针中不存储大小信息)。但是指针有一个类型,编译器会将指针所指的内存位置解释为该类型的对象。存储在指针外部的额外信息允许编译器执行转换。

【讨论】:

    【解决方案2】:

    a 变量将指向分配的b 对象的A 类部分。指针只是一个内存地址,仅此而已。重要的是指针指向内存中的数据类型。

    【讨论】:

      【解决方案3】:

      让我们把答案分成三个部分

      指针

      指针是一个变量,它保存另一个变量的内存地址。指向变量的类型很重要,编译器会检查它。可以通过使用指向 void 的指针来强制使用指针机制(在 C++ 中应避免使用,除非您真的知道自己在做什么)。

      使用基类指针访问派生类对象

      派生类(代码中的b)的对象(即变量)可以使用指向其父类型的指针(代码中的A)来引用。这将允许您访问存在于B 中的 A 的成员。正如 Richard J. Ross 所述,使用指向基类的指针将产生与使用派生类指针相同的地址(除非涉及多重继承)。

      虚函数

      虚拟方法允许您使用基类指针调用派生对象的重载方法。这对于析构函数特别有用,因为可以放心,即使使用基类指针,对象也会被正确销毁(假设析构函数写得很好)。

      不过,您的代码在概念上是错误的。因为A的析构函数不是虚拟的,所以bB部分的析构函数不会被调用,因此可能会出现内存泄漏等问题。

      【讨论】:

      • 感谢解答,我知道程序错了,特意弄成这样。但问题是a和b的地址不一样,
      【解决方案4】:

      正如大卫已经提到的,两个指针a == b 的简单比较会给你 True 因为编译器会将它们都转换为公共类型。 但是,如果您将其修改为(void*)a == (void*)b,结果可能为假。 这是因为 A 类和 B 类有不同的内存布局,因为 B 有一个虚函数表,而 A 没有。

      MSVC 编译器将虚函数指针放在类的“顶部”,在第一个数据成员之前,但没有什么能阻止其他编译器将它放在“底部”。

      您也可以尝试将 A 类析构函数设为虚拟。

      【讨论】:

        【解决方案5】:

        我在c++对象模型里面找到了一些解释,这就像多重继承,vptr位于对象的开头。 当基类没有virtual而子类有virtual时,指针的赋值将由编译器通过vptr逐步调整,

        【讨论】:

          【解决方案6】:

          示例是两个指针之间的比较。因为它们指向同一个位置,所以 a 将等于 b。

          【讨论】:

          • 不,a和b指向的不是同一个地址,在win32,vc2005上测试过
          • 糟糕,我现在明白了,所以 a 不等于 b。
          • 那么您是在比较指针还是在取消引用指针后比较,即 if (*a==*b)?
          猜你喜欢
          • 2014-12-21
          • 1970-01-01
          • 2018-07-05
          • 1970-01-01
          • 2010-09-25
          • 2012-07-07
          • 2012-05-18
          • 2017-05-06
          • 2012-03-30
          相关资源
          最近更新 更多