调用成员函数而不初始化指针变量

时间:2014-04-02 17:43:05

标签: c++ pointers member

我创建了两个类,A和B. B包含一个指向A的指针,但从不初始化A.但是,我可以在不初始化A的情况下调用A的函数。如何/为什么这可能?

 class A
{
public:
    void Test() {
        printf("Test from A\n");
    }
};


class B
{

public:
    B() {
    }
    ~B() {
    }
    void T() {
        a->Test();
    }
private:
    A* a;
};


int main() {

    B b;
    b.T();
    /*
    B* b;
    b->T();    //This does not work, as expected. So why can I call a->Test via b.T(), and have that work when a was never initialized?
    */

    system("PAUSE");
    return 0;
}

2 个答案:

答案 0 :(得分:1)

这是因为编译器在内部将a-> Test()之类的调用转换为稍微不同的形式:

A::Test(a);

正如你所看到的,它调用的函数只是一个地址,它被调用的对象作为参数传递,可以是nullptr / uninitialized / anything。

对于虚拟功能,它将几乎相同,涉及更多细节:

a->vtbl[0](a);

其中vtbl是一个虚函数指针表,通常在对象构造时初始化,但它的偏移量通常在编译时就已知,这就是为什么编译器实际上没有任何麻烦“调用”它的对象不存在 - 它只会从随机存储器位置读取垃圾并快乐地使用它。

答案 1 :(得分:0)

虽然a *的值未定义,但我相信实际定义了此代码的行为。

测试功能的真实标题将生成为: void Test(A* this); 含义 - 它是一个简单的C函数,它将结构的指针作为其第一个参数。

由于你的b对象中有一个初始化的对象(由它指向的内存中的任何驻留随机初始化),当你调用a-> test()时,你将正确调用Test函数(使用相同的函数)随机作为"这个")的值。由于你没有使用"这个"在Test中,它实际上会按预期工作。