简体   繁体   中英

Is it ok to declare/define a static method in the .cpp only?

In many cases I find my classes needing private functions to break down their functionality and reuse code. The typical implementation would be :

MyClass.h

#include "AnotherClass.h"

class MyClass {
public:
    float foo() const;
private:
    float fooPrivate(const AnotherClass& ac) const; 
}

MyClass.cpp

#include "MyClass.h"

float MyClass::foo() const {
    return fooPrivate(AnotherClass());
}
float MyClass::fooPrivate(const AnotherClass& ac) const {
    return ac.foo();
}

This is ok, however declaring fooPrivate() in the header file can be problematic in the following cases :

  • we might not want to include AnotherClass in the header file if it is only for internal uses and is not needed outside MyClass.

  • if many private functions are needed we risk polluting the header file with unnecessary private functions that make code less clear, increase compile time and is more difficult to maintain.

I am aware of the Pimpl idiom that solves all these problems but my question is if we do not want to use the Pimpl is it ok to do something like this for a few functions ?

MyClass.h

class MyClass {
public:
    float foo() const;
}

MyClass.cpp

#include "MyClass.h"
#include "AnotherClass.h"

static float fooPrivate(const AnotherClass& ac) {
    return ac.foo();
}
float MyClass::foo() const {
    return fooPrivate(AnotherClass());
}

In this case it is not needed to include AnotherClass.h in MyClass.h and fooPrivate() can not be called by anyone except from inside MyClass.cpp and after it has been declared. Am I right?

Are there any caveats using this or will I end up with problems when my program gets bigger?

Actually, not only is it okay, I would actually recommend it.

private functions may be used, and sometimes must (when accessing private elements) however there is one issue with them: even if it is only a declaration, they clutter the class definition: a user of the class should not have to care or be exposed to the class internals.

On the other hand, static functions or functions declared in an anonymous namespace within a source file are "free". No matter how many of them you have:

  • they do not clutter the header
  • on Itanium ABI compiler tool-chains (for example), they do not lead to an exported symbol, speeding up load time

If there is one downside, though, it is that on those same Itanium-related tool-chains their absence of name make for poor backtraces without debug symbols. It can be seen as a minor inconvenience though.

Note: not having access directly to private members of the class is rarely an issue because a method of the class can easily pass a reference to those members to them. It does mean they cannot build an instance of the class when the constructors are not public however.

There are no caveats, except slight inconvenience. Your static function is not going to be a class method, obviously. Because of that, it can only access public class members and methods.

I do this occasionally, for "helper functions" that have literally no use whatsoever in the class's public interface. I try to minimise the use of this pattern as there is no access to private variables. However, free functions are a good thing and arguably even increase encapsulation .

As your helper-function does only use the public interface of the class, using a static function only available in the classes implementation-file is fine.

Anyway, your example did not actually need the definition of AnotherClass , a lightweight forward-declaration would have been fine:

class AnotherClass;

Also, I would mark the function inline in both cases on general principles, iff it is used only by the implementation, and that is all together in the same translation-unit:
There would be a slight chance of better performance / smaller code, without any downsides.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM