命名空间中的函数重载(与具有静态成员的类相比)是一个坏主意吗?

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
    

因此,最佳实践始终是在定义/调用之前声明原型 :)

【讨论】:

感谢您的回答。我担心的一个问题是,我是否应该避免练习使用命名空间,其中一组函数可以以静态方式包装在一个类中?

以上是关于命名空间中的函数重载(与具有静态成员的类相比)是一个坏主意吗?的主要内容,如果未能解决你的问题,请参考以下文章

私有静态成员函数或匿名命名空间中的自由函数?

指向重载静态成员的函数指针 - 在 unique_ptr 中用作自定义删除器

具有相同命名空间名称时的模拟库函数

C++ 多态性和重载?

[C++]——函数的重载

单例类与具有静态成员的类