【问题标题】: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 以调用自身,结果是stackoverflow。

尽管改变函数的顺序可以解决问题,但我想知道在专业 C++ 编程中在命名空间中使用函数重载是不是一个坏主意?

【问题讨论】:

  • 问题不在于函数重载,而在于确保调用时要调用的定义在范围内。
  • 如果这是在命名空间之外,你会得到同样的错误。类是特殊的(出于某种原因)。
  • 很遗憾,意识形态问题。您会发现很多编码标准会建议“永远不要超载。EVER”,尤其是在清晰度和可预测性是基本要求的安全关键型应用程序中。没有人希望火箭在一百英尺高的地方引爆,因为 bool 恰好更适合。
  • 至于具体问题,(1)关于真正的问题:在专业编程中,您通常希望在头文件中声明您的函数,并在其他地方定义它们(通常在 .cpp文件,但偶尔在同一个头文件中),除非您不想公开该函数。最终结果是您无需担心定义函数的顺序。 (2) 我有一份工作不鼓励重载,并建议让参数类型显而易见,getUserIdByUsername()、getUserIdForAdmin() 等。我不喜欢它。

标签: c++ class namespaces


【解决方案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
    }
}

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

【讨论】:

  • 感谢您的回答。我担心的一个问题是,我是否应该避免练习使用命名空间,其中一组函数可以以静态方式包装在一个类中?
猜你喜欢
  • 2018-04-16
  • 2011-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-24
  • 1970-01-01
  • 2012-05-27
  • 2019-11-29
相关资源
最近更新 更多