在C++(类)中,我是否总是需要在头文件中声明函数?

6
例如,我有一个markerdisplay.cpp文件。markerdisplay成员函数将如下代码所示。
void MarkerDisplay::setMarkerStatus(MarkerID id, StatusLevel level, const std::string& text)
        {
               .....
        }

我能在markerdisplay.cpp中使用非成员函数吗?

比如说,

bool validateFloats(const visualization_msgs::Marker& msg)
        {
              ...
        }

函数validateFloats不是成员函数,也没有在头文件中声明。我只在validateFloats.cpp文件中使用这个函数。

有人告诉我这可能会引起一些问题。这是真的吗?


1
当你在其他文件中包含头文件时,你使用头文件来进行原型声明(或者在某些情况下进行显式声明)。如果没有原型声明,链接器将无法在调用函数时找到它。 - Shawnic Hedgehog
1
@ShawnicHedgehog 如果没有原型,链接器在调用函数时将无法找到它,这并不准确,“在调用它时”在这里也没有意义。原型和声明之间有什么区别? - Ryan Haining
我曾经以为 OP 正在寻求其他东西。在看起来像明目张胆的白痴之前阅读帖子是有帮助的。 - Shawnic Hedgehog
1
另一个小澄清,缺少原型会惹怒编译器,而不是链接器。 - user4581301
感谢所有的答案。点赞! - Allen Yuan
显示剩余4条评论
2个回答

14
如果您不需要在.cpp文件之外使用该函数,则只需在该文件中声明和定义即可。当然,在第一次使用之前仍然需要进行声明,但这是我能想到的唯一的“问题”。
如果不需要在头文件中声明该函数,那么这实际上是一个不错的主意,因为您可以节省更少的“项目公共”名称,并且更容易找到所有使用该函数的地方,从而使代码更易于维护。
如果您不在头文件中声明该函数,则应将其设置为static
static bool validateFloats(const visualization_msgs::Marker& msg);

或将其放置在匿名命名空间中:

namespace {
    bool validateFloats(const visualization_msgs::Marker& msg);
}

(首选)为了避免意外的跨翻译单元名称冲突。


1
我认为匿名命名空间是正确的选择。private static并不能真正将实现隐藏起来,以防止链接。 - πάντα ῥεῖ
C++03中没有匿名命名空间吗?我肯定用过它们,但不记得它们是否被标准支持。 - juanchopanza
@Baum “所以在C++中,如果在翻译单元中定义了static,它应该可以很好地隐藏名称,但在头文件中公开是没有意义的。” - πάντα ῥεῖ
@πάνταῥεῖ "但仅当在翻译单元中定义时才有效。在头文件中公开是没有意义的。" 当然,在C或C++中都没有意义。抱歉,我没有意识到我谈论的是一个未在头文件中声明的函数。 - Baum mit Augen
2
@AllenYuan 不用谢!请注意,“感谢”评论会被视为噪音。相反,您可以通过点击旁边的复选标记接受您认为最有用的答案。 - Baum mit Augen
显示剩余12条评论

7
我的问题是:我能在markerdisplay.cpp中有非成员函数吗,例如...
可以的。
最好的选择是,如果该函数不打算从公共API中使用,则在实现翻译单元中提供该函数。
甚至可以在匿名命名空间中完全隐藏它(包括链接器)。
namespace {
    bool validateFloats(const visualization_msgs::Marker& msg) {
       // ...
    }
}

或者在翻译单元中定义一个静态函数也会有同样的效果:

static bool validateFloats(const visualization_msgs::Marker& msg) {
   // ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接