重载一个函数同时获取指针或引用是不是一种糟糕的做法

Is it bad practice to overload a function to take both a pointer or a reference?

本文关键字:一种 是不是 引用 指针 函数 一个 重载 获取      更新时间:2023-10-16

例如,如果我有一个结构FooSpec:

struct FooSpec { /* lots of data */ };

将以下两个都作为重载函数提供是不是一种糟糕的做法?还是我应该选择一个并坚持下去?

Foo *createFoo(const FooSpec *spec) { /* ... */ }
Foo *createFoo(const FooSpec &spec) { return createFoo(&spec); }

两者兼而有之会引发意想不到的问题吗?

应该只有一种方法来做特定的事情。这将使代码对用户更加清晰。因此,根据语义,您应该只选择一个:

  • 如果nullptr是一个要传递给createFoo的有意义的值,那么声明该函数接受指针。

  • 如果nullptr不应该传递给createFoo,那么将参数声明为引用,以使编译器对试图传递nullptr的人大喊大叫。

现在,代码的用户会说"啊,我可以给那个函数传递一个null,很酷!"或者"好吧,这个函数需要一个实际的对象才能正常工作"。

在整个项目中坚持这个约定,以使代码的接口更加连贯。

或者正如WhozCraig所说,

选择合适的型号并告诉客户"这是你的界面。"

我能想出一个稍微有用的理由来做这件事。

Foo*版本可以检查null,处理该情况,如果不使用引用情况。

Foo&则不能检查是否为空。

这让调用者说"我知道这不是null,因为我检查了",从而在函数中保存了一个分支。

然而,一旦该方法的成本通过非常低的阈值,这种好处(节省分支)就毫无意义了。

软件代码库不是一个静态对象,它是随着使用它的人的需求而发展的。如果一个令人困惑的界面是"糟糕的做法"(我宁愿说这是一件愚蠢的事情),那么代码库可能会在重构和代码改进的过程中发展到这种情况。

在这种情况下,如果您正在迁移编码约定以使用引用而不是常量指针(或者相反,但这对我来说没有多大意义),这并不是一种糟糕的做法。这里的坏做法可能是进行这些演变,而不是记录它,因为其他人不知道其中一种方法被弃用,或者只是不知道该使用哪种方法。

还有可能传递带有常量指针的nullptr_t(或像我这样的老计时器的NULL指针)。我不确定这样做的好处,因为您可以在方法的参数上重载方法,但同样,在不断变化的API环境中,这是有意义的。


†它还活着

相关文章: