简体   繁体   English

重载函数以获取指针或引用是不好的做法吗?

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

For example, if I had a struct FooSpec : 例如,如果我有一个结构FooSpec

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

Is it bad practice to provide both of the following as overloaded functions? 将以下两个都作为重载函数提供是不好的做法吗? Or should I just choose one and stick with it? 或者我应该选择一个并坚持下去?

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

Could having both cause unexpected problems? 两者都会导致意想不到的问题?

There should be only one way to do a specific thing. 应该只有一种方法来做某件事。 This will make the code clearer for its users. 这将使代码更清晰。 Therefore, you should pick only one, depending on the semantics: 因此,您应该只选择一个,具体取决于语义:

  • If a nullptr is a meaningful value to be passed to createFoo , then declare the function to take a pointer. 如果nullptr是要传递给createFoo的有意义的值,则声明该函数采用指针。

  • If a nullptr shouldn't be passed to createFoo , then declare the parameter a reference to make the compiler yell at people who try pass in a nullptr . 如果不应将nullptr传递给createFoo ,则将参数声明为引用,以使编译器对尝试传入nullptr人大喊大叫。

Now the users of your code will go "Ah, I can pass a null to that function, cool!" 现在你的代码的用户将会“啊,我可以将null传递给该函数,很酷!” or "Okay this function needs an actual object to work properly". 或“好的,这个功能需要一个实际的对象才能正常工作”。

Stick to this convention throughout a project to make the interface of the code more coherent. 在整个项目中坚持这一惯例,使代码的界面更加连贯。

Or as WhozCraig put it, 或者像WhozCraig所说的那样,

Pick the appropriate model and tell the clients "this is your interface." 选择合适的模型并告诉客户“这是您的界面”。

I can think of one marginally useful reason to do this. 我可以想到这样做的一个有用的原因。

The Foo* version can check for null, handle that case, and if not use the reference case. Foo*版本可以检查null,处理该情况,如果不使用参考案例。

The Foo& can then not check for null. Foo&然后可以不检查null。

This lets callers say "I know this is not null because I checked", saving a branch within the function. 这让调用者说“我知道这不是空的,因为我检查了”,在函数中保存了一个分支。

However this benefit (saving a branch) is pointless once the cost of the method passes a very low threshhold. 然而,一旦该方法的成本通过非常低的阈值,这种好处(保存分支)是没有意义的。

A software codebase is not a static object, it evolves with the needs of those who use it. 软件代码库是不是一个静态的对象,它的发展与那些谁使用它的需求。 If a confusing interface is "bad practice" (I would rather say a silly thing to do), a codebase may end up in such situation as it evolves from refactoring and code improvement. 如果一个令人困惑的界面是“不好的做法”(我宁愿说一件愚蠢的事情要做),代码库可能最终会出现从重构和代码改进演变而来的情况。

In this instance, it's not bad practice if you're in the process of migrating your coding conventions to use references instead of const pointers (or the opposite, but that doesn't make much sense to me). 在这种情况下,如果您正在迁移编码约定以使用引用而不是使用const指针(或者相反,但这对我来说没有多大意义),那么实践并不错。 The bad practice here would probably to make these evolutions and not document it, with other people not knowing that one of these methods is deprecated, or simply which one to use. 这里的不良做法可能是进行这些演变而不是记录它,而其他人不知道这些方法中的一个被弃用,或者只是使用哪一个。

There's also the possibility of passing a nullptr_t (or NULL pointers for old timers like me) With const pointers. 还有可能使用const指针传递nullptr_t (或像我这样的旧定时器的NULL指针)。 I am not sure of the benefit of this, given that you can overload methods on their arguments, but again in the context of a changing API it makes sense. 我不确定这有什么好处,因为你可以在他们的参数上重载方法,但是在更改API的上下文中它是有意义的。


† it's alive!!! † 它还活着!!!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM