空指针的相关性

时间:2018-12-19 13:18:49

标签: c++ refactoring

查看同事的代码,我发现它的某些句柄存储为空指针。

// Class header
void* hSomeSdk;

// Class implementation
hSomeSdk = new SomeSDK(...);
((SomeSDK*)hSomeSdk)->DoSomeWork();

现在我知道有时句柄是空指针,因为在运行时之前可能不知道句柄的实际类型是什么。或者,当我们需要共享指针而不公开其实际结构时,它可以提供帮助。但这在我的情况下似乎不是这样:它将始终是SomeSDK,并且不会在创建它的类之外共享。这段代码的作者也来自公司。

还有其他原因使它成为空指针有意义吗?

3 个答案:

答案 0 :(得分:1)

不。

如果我不得不猜测,这位前同事不熟悉转发声明,因此不知道他们仍然可以在标题中执行SomeSDK*,而不必包括整个{{1 }}定义。

鉴于您提到的约束,此模式实现的唯一目的是消除某种类型的安全性,使代码更难于阅读/维护,并产生堆栈溢出问题。

答案 1 :(得分:1)

由于这是一个成员变量,所以我要大步走出去,说您的同事想最小化依赖性。仅定义指针可能不希望包含SomeSDK的标头。从您显示的代码来看,该同事可能有两个原因之一:

  1. 他们只是不知道可以添加诸如class SomeSDK;之类的前向声明来允许定义指针。有些程序员只是不知道它。
  2. 他们不能转发声明。如果SomeSDK不是类,而是类型别名(又名typedef),则无法准确地向前声明它。只能声明其别名的类,但这又可能是难以跟踪的实现细节。甚至标准库也有类似的问题,这就是为什么它提供iosfwd以便更轻松地向前声明标准流类型的原因。

如果代码中带有该句柄的样式,则该设计应该在很久以前就已进行了重新设计。否则,如果仅在一个地方(或最多几个地方),我就能明白为什么维护它的人们可以和平地生活。

答案 2 :(得分:1)

void*很流行,需要在C语言中使用。它们在方便地转换为任何东西的意义上很方便。如果您需要从double*投射到char*,则必须对void*进行中间投射。

void*的问题在于它们过于灵活:它们无法传达作者的意图,这使得它们非常不安全,尤其是在大型项目中。

在面向对象设计中,通常会创建抽象接口类(所有成员都是虚拟的且未实现),并指向此类,然后根据用途实例化各种可能的实现。

但是,如今,更建议使用模板(C ++相对于其他语言而言的主要优势),因为它们速度更快,并且比OOD允许的编译时间优化更多。不幸的是,使用模板仍然是一个巨大的麻烦-它们的语法更加复杂,并且很难将编写者的意图传达给用户有关模板参数的限制和要求(C + +可以很好地解决此问题的概念TS +20-目前只有SFINAE,这是20年前的一个可怕的临时解决方案;而Reflection TS将大大增强C ++中的通用编程,即使在C ++ 23中也不太可能提供。