C ++概念访问公共方法

时间:2011-11-17 05:11:03

标签: c++ public-method

#include <iostream>

class Test {
public:
    int i;
    void print()
    {
        std::cout << "Hello" << std::endl;
    }
};

int main()
{
    class Test *p = NULL;
    p->print();
    (*p).print();
}

Output:

Hello
Hello

我理解对象方法和成员变量存储在内存中的不同位置,但是p被指定为NULL时如何解析调用Test::print()

Test6:~ 1001> g++ --version
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Test6:~ 1002> g++ manoj.cpp
Test6:~ 1003> ./a.out
Hello
Hello
Test6:~ 1004> cat manoj.cpp
#include <iostream>

class Test {
public:
int i;
void print()
{
std::cout << "Hello" << std::endl;
}
};

int main()
{
class Test *p = NULL;
p->print();
(*p).print();
}
Test6:~ 1005>

3 个答案:

答案 0 :(得分:3)

除非类具有虚函数(即编译器不创建vtable),否则所有指向方法的指针都将在程序中进行硬编码,因此不需要任何变量信息。但是,即使在这种情况下,它也没有有效的this指针,因此它仍会崩溃。

答案 1 :(得分:0)

你根本做不到这一点。 此代码无法编译,并且您无法寻址空指针。尝试使用:

int main()
{
    // no need for 'class' keyword when declaring the pointer:
    Test* p = new Test(); // use default constructor provided by compiler
    p->print();
    (*p).print();
    // you also need to delete the pointer before returning, but that's irrelevant
    return 0; // you need this too
}

答案 2 :(得分:0)

你所做的不是一个“良好开发的代码片段”,但是它有效,因为即使this指针为null,你也不会(明确地或隐含地)取消引用它。

你的* p(或p->)属于Test类,而Test::print没有引用Test中的任何内容,所以......因为 null测试总是 Test ,你不关心它的内容,代码编译和工作。

但如果符合以下条件,此代码将遇到麻烦:

  • Test::print是虚拟的:在这种情况下,p->print()(或(*p).print())必须通过实际对象的v表来检测要调用的函数。 (*p可以是Test派生的任何内容,但由于没有对象,因此无法检测到v-table,程序将崩溃。
  • Test有一个成员,你的print函数用于打印它:在这种情况下,由于p指向一个无效的内存块,你的函数--wile访问成员变量 - 将尝试隐式取消引用null此指针以计算成员的位置。并且会导致内存地址无效,从而导致崩溃。

事实上,你刚刚进入了一个名为“ undefined behavior ”的灰色区域:语言律师(编写规范的人)对此没有任何说法(特别是:从未说过) “取消引用无效指针是一个(运行时)错误”:他们说“取消引用无效指针会导致未定义的行为”,这几乎意味着“我们不想要”告诉你应该发生什么“)。

但是由于编译器编写者必须做某事(编译器不能“未定义”),因为在编译时 - 翻译一行代码 - 他们无法知道指针的值是什么,他们决定翻译任何方式的代码。

由于代码的执行不会破坏任何进程边界,因此不会崩溃。 并且由于没有访问“正在进行未初始化的空间”,因此看不到杂乱的值,一切看起来都不错。

欢迎使用非托管语言字!