C ++,指针真的意味着什么?当虚拟涉及

时间:2012-09-26 01:12:38

标签: c++ pointers virtual

以下代码

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”?为什么以及如何发生? 什么指针真的意味着什么?不只是一个地址和内存块的长度?

6 个答案:

答案 0 :(得分:3)

  

将“a”等于“b”?

  

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

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

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

指针究竟意味着什么?不只是一个地址和内存块的长度?

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

让我们分三个部分分开答案

指针

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

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

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

虚拟功能

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

仍然,您的代码在概念上是错误的。因为A的析构函数不是虚拟的,所以B b部分的析构函数不会被调用,因此可能存在内存泄漏和类似问题。

答案 3 :(得分:0)

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

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

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

答案 4 :(得分:0)

我在内部c ++对象模型中找到了一些解释,这就像多重继承一样,vptr位于对象的开头。 当基类没有虚拟子类和子类时,指针的赋值将由编译器逐步调整为vptr,

答案 5 :(得分:-1)

该示例是两个指针之间的比较。当他们指向相同的位置时,a将等于b。