提示:在C++,使用不使用"this"的方法不是好的设计
TIP: in C++, having a method where "this" is not used is not good design
在本质上,类的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();
你甚至不需要有一个对象或指针就可以做到这一点。
相关文章:
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 没有为自己的结构调用列表推回方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 在类定义之后定义一个私有方法
- 枚举环境变量的惯用C++14/C++17方法
- 初始化具有非默认构造函数的std::数组项的更好方法