提示:在C++,使用不使用"this"的方法不是好的设计

TIP: in C++, having a method where "this" is not used is not good design

本文关键字:方法 C++ 提示 this      更新时间:2023-10-16

在本质上,类的C++方法就像C函数,其第一个参数是类或结构的实例。

例如:

void Foo::Do();

将等同于C:中的声明

void Do(Foo* this);

因此,在方法中使用成员m_someMember就像在C函数中使用this->m_someMember。

经过这么多年的C/C++编程经验,我最近刚刚问自己:如果我从一个NULL的实例指针中调用一个方法怎么办

我的猜测是:如果该方法根本没有引用任何成员,那么它什么时候会崩溃

所以我做了一个快速测试(在Windows平台上,使用Visual C++2008):

class Foo
{
public:
    Foo() {}
    virtual ~Foo() {}
    void Do();
};
void Foo::Do()
{
    cout << "Calling 'Do' for " << this << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
    Foo foo;
    foo.Do();
    Foo* pNullFoo = 0;
    pNullFoo->Do();
    return 0;
}

其输出类似于:

Calling 'Do' for 0038FE5C
Calling 'Do' for 00000000

当对null实例指针进行崩溃的事后调试时,这可能会很麻烦。您可能会认为,如果无效,则无法调用此方法。

另一方面,如果方法被声明为虚拟的:

virtual void Foo::Do() { ... }

然后行:

pNullFoo->Do();

将产生页面错误异常。为什么?因为具有虚拟方法的类的实例有一个指向vtable的指针,指向它们所属的子类虚拟方法。所以编译器要做的第一件事就是让pNullFoo访问它的vtable成员,然后砰!

总之,这是一个更好的设计,让像Do这样的非上下文函数作为过程例程来实现,而不是方法,除非它们是虚拟的。

在NULL指针上调用成员函数会调用未定义的行为。未定义并不意味着它会崩溃,也不意味着它将做正确的事情——这是未定义的。任何事情都有可能发生。

我唯一一次在生产代码中看到这种情况是使用Microsoft的CWnd::GetSafeHWND函数。但既然他们编写了编译器,他们就可以逍遥法外

对于不需要访问任何成员数据的成员函数,正确的设计是将它们定义为静态:

static void Do();

然后称之为:

Foo::Do();

你甚至不需要有一个对象或指针就可以做到这一点。