命名空间中的函数重载(与具有静态成员的类相比)是一个坏主意吗?
Posted
技术标签:
【中文标题】命名空间中的函数重载(与具有静态成员的类相比)是一个坏主意吗?【英文标题】:Is function overloading in a namespace (compared to a class with static members) a bad idea? 【发布时间】:2015-07-14 01:04:25 【问题描述】:这是一个关于想法而不是真实代码的问题
过去我总是写很多方法重载,这很好:
class myclass
public:
std::string method(type1 a)
return method(...);
std::string method(type2 a)
return ....;
这太棒了。
问题从昨天写的函数重载是命名空间开始:
namespac myspace
std::string func(type1 a)
return func(...);
std::string func(type2 a)
return ....;
这里的问题是,在命名空间内部,编译器不知道第二个函数。因此,它尝试将给定类型转换为与第一个函数匹配的内容。不幸的是,编译器没有告诉我这是我的错误。虽然我向函数发送了type2
,但它试图将其转换为type1
以调用自身,结果是***。
尽管改变函数的顺序可以解决问题,但我想知道在专业 C++ 编程中在命名空间中使用函数重载是不是一个坏主意?
【问题讨论】:
问题不在于函数重载,而在于确保调用时要调用的定义在范围内。 如果这是在命名空间之外,你会得到同样的错误。类是特殊的(出于某种原因)。 很遗憾,意识形态问题。您会发现很多编码标准会建议“永远不要超载。EVER”,尤其是在清晰度和可预测性是基本要求的安全关键型应用程序中。没有人希望火箭在一百英尺高的地方引爆,因为bool
恰好更适合。
至于具体问题,(1)关于真正的问题:在专业编程中,您通常希望在头文件中声明您的函数,并在其他地方定义它们(通常在 .cpp文件,但偶尔在同一个头文件中),除非您不想公开该函数。最终结果是您无需担心定义函数的顺序。 (2) 我有一份工作不鼓励重载,并建议让参数类型显而易见,getUserIdByUsername()、getUserIdForAdmin() 等。我不喜欢它。
【参考方案1】:
正如有人评论的,这个问题不是函数重载,而是函数声明的顺序。
当编译器看到时,您的命名空间中的错误很明显
std::string func(type1 a)
return func(/*expect type2*/);
当时它必须知道func(/*expect type2*/)
的原型/定义。
但是,在你的类定义中:
class myclass
public:
std::string method(type1 a)
return method(/*expect type2*/); // OKAY, no problem here
std::string method(type2 a)
return ....;
尽管method(/*expect type2*/)
的原型/定义在该位置未知,但编译器不会抛出任何错误。为什么?
据此http://www.tutorialspoint.com/cplusplus/cpp_inline_functions.htm
类定义中的函数定义是内联函数定义,即使不使用内联说明符。
也就是说,编译器在编译myClass
时,只编译了成员prototype,当然,在这个例子中,没有错误。成员 definition 将在稍后编译,例如当您调用该成员时。此时,myClass
中的所有成员函数原型都已完全知晓。因此,编译器不会抛出任何错误。
编辑:命名空间是命名空间,类是类;它们有不同的含义。选择命名空间或类取决于您自己的情况,而不是摆脱函数顺序错误的愿望。在您的示例中,您仍然可以通过声明所有需要的原型来使用命名空间:
namespac myspace
std::string func(type2 a); // prototype
std::string func(type1 a)
return func(...); // fine
因此,最佳实践始终是在定义/调用之前声明原型 :)
【讨论】:
感谢您的回答。我担心的一个问题是,我是否应该避免练习使用命名空间,其中一组函数可以以静态方式包装在一个类中?以上是关于命名空间中的函数重载(与具有静态成员的类相比)是一个坏主意吗?的主要内容,如果未能解决你的问题,请参考以下文章