6

For example, I have a markerdisplay.cpp file. The markerdisplay member function will look like the below code.

void MarkerDisplay::setMarkerStatus(MarkerID id, StatusLevel level, const std::string& text)
        {
               .....
        }

Can I have a non-member function in the markerdisplay.cpp?

For example,

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

The function validateFloats is not a member function, and I also don't declare it in the header file. I only use this function inside of the validateFloats.cpp file.

Someone told me this may cause some problems. Is that true?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Allen Yuan
  • 77
  • 1
  • 6
  • 1
    You use the header for prototypes (or in some cases explicit declarations), when you include the header in other files, if there is no prototype, the linker will not be able to find the function when you call it. – Shawnic Hedgehog Mar 13 '17 at 23:03
  • 1
    @ShawnicHedgehog "*if there is no prototype, the linker will not be able to find the function when you call it*" this is not accurate, and "when you call it" doesn't really make sense here. What is the difference between a prototype and a declaration? – Ryan Haining Mar 13 '17 at 23:07
  • Prototypes are all about scope. Guess I should've clarified a little better. And the statement regarding the prototype: if you declare a function in a *.cpp file, and you don't put the prototype in the *.hpp file, how is the compiler going to find that function when you only include the *.hpp file? – Shawnic Hedgehog Mar 13 '17 at 23:16
  • @ShawnicHedgehog The compiler won't need to "find" the function because it is only used in the `.cpp` file in which it is declared and defined. – juanchopanza Mar 13 '17 at 23:19
  • I was under the assumption that OP was asking for something else. It helps to read posts before looking like a blatant idiot. – Shawnic Hedgehog Mar 13 '17 at 23:21
  • 1
    Another small clarification, a missing prototype will anger the compiler, not the linker. – user4581301 Mar 13 '17 at 23:22
  • thanks for all the answers. Thumb up! – Allen Yuan Mar 14 '17 at 00:04
  • @ShawnicHedgehog you are confusing "declaration" and "definition" – Ryan Haining Mar 14 '17 at 01:41
  • @RyanHaining you are correct. My bad. – Shawnic Hedgehog Mar 14 '17 at 01:43

2 Answers2

14

If you don't need the function outside of the .cpp, it is sufficient to declare and define it in that file. Of course you will still have to declare it before first use, but that is the only "problem" I can think of.

It is rather a good idea not to declare the function in the header if not needed because you use up fewer "project-public" names and make it easier to find all uses of the function, thus making the code more maintainable.

If you don't declare the function in your header, you should make it static:

static bool validateFloats(const visualization_msgs::Marker& msg);

or put it in an anonymous namespace:

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

(preferred) to avoid accidental cross-translation-unit name clashes.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • 1
    I think anaonymous namespace is the way to go. `private static`isn't really hiding that implementation from linking. – πάντα ῥεῖ Mar 13 '17 at 23:10
  • @πάνταῥεῖ Totally agree, but the sad and ugly truth is that C++03 is still widely used and taught, so I mentioned both and remarked the `namespace{}` is preferred. – Baum mit Augen Mar 13 '17 at 23:12
  • Weren't anonymous namespaces available in C++03? I certainly used them, but don't recall if they were supported by the standard. – juanchopanza Mar 13 '17 at 23:14
  • @juanchopanza I believe they did not imply internal linkage pre-C++11, but that might be wrong. I was fortunate enough to just skip that era, I wasn't programming yet back then. :) – Baum mit Augen Mar 13 '17 at 23:16
  • @Baum Just curious: For pre c++11, would `static` behave the same way as c code does (regarding linker privacy)? I've got a badly downvoted question regarding this: [C static keyword vs C++ private scope?](http://stackoverflow.com/questions/29224679/c-static-keyword-vs-c-private-scope) – πάντα ῥεῖ Mar 13 '17 at 23:17
  • C++03? That's some high tech smurf in a world where *TurboC++* is still widely taught. – user4581301 Mar 13 '17 at 23:20
  • @πάνταῥεῖ I think so. The main difference (linkage wise, names aside) between C++11 anonymous namespaces and `static` would be that the former allows you to define types with internal linkage. – Baum mit Augen Mar 13 '17 at 23:20
  • @user4581301 India isn't _widely_, or _the world_ . And as long they keep that in their educational systems, it's unlikely they'll keep up in long term. – πάντα ῥεῖ Mar 13 '17 at 23:24
  • @Baum But in c `static` means module local, so there's no way to link those definitions from an external module. While for c++ only the anonymous namespace guarantees that. – πάντα ῥεῖ Mar 13 '17 at 23:27
  • @juanchopanza Not sure, but I think that feature was introduced with c++11. Well we have these limbo years with half-baked standard implementations which were supported by default. – πάντα ῥεῖ Mar 13 '17 at 23:29
  • @Baum In your answer it's a bit unclear, **where** to make that function `static`. The OP clearly asks if it's possible to avoid the declaration in the header fle. – πάντα ῥεῖ Mar 13 '17 at 23:32
  • @πάνταῥεῖ I read the relevant quote (*"When a name has internal linkage , the entity it denotes can be referred to by names from other scopes in the same translation unit."*, from the answer to the Q you linked above) as an exhaustive list, so `static` should hide the name from the linker just fine in C++ too. – Baum mit Augen Mar 13 '17 at 23:33
  • @Baum _"so static should hide the name from the linker just fine in C++ too."_ But only if that's defined in the translation unit. Exposing in a header wouldn't make sense. – πάντα ῥεῖ Mar 13 '17 at 23:34
  • @πάνταῥεῖ I hoped that was clear, but tried to clarify further. Thx. – Baum mit Augen Mar 13 '17 at 23:35
  • @πάνταῥεῖ *"But only if that's defined in the translation unit. Exposing in a header wouldn't make sense."* Of course, that wouldn't make sense in neither C nor C++. Sorry, I was not aware that it's unclear I was talking about a function *not* declared in the header. – Baum mit Augen Mar 13 '17 at 23:36
  • @Baum I don't think that question I posed was really that silly. It's just a likely target picked up by revenge voters against me ;-). – πάντα ῥεῖ Mar 13 '17 at 23:37
  • 2
    @AllenYuan You are welcome! Note that "Thank you"-comments are frowned upon because the count as noise. Instead, you can accept the answer you find most useful by clicking the checkmark next to it. – Baum mit Augen Mar 14 '17 at 00:03
7

my question is: can I have non member function in the markerdisplay.cpp for example ...

Yes, you can do that.

The best choice would be to provide that function in the implementing translation unit if it's not intended to be used from the public API.

You can even completely hide that (including the linker) in an anonymous namespace

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

Alternatively just defining a static function in the translation unit should have the same effect:

static bool validateFloats(const visualization_msgs::Marker& msg) {
   // ...
}
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190