Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Declaration of class variables in header or .cpp?

So far, I've been using classes the following way:

GameEngine.h declares the class as follows

class GameEngine {
public:
    // Declaration of constructor and public methods

private:
    InputManager inputManager;
    int a, b, c;

    // Declaration of private methods
};

My GameEngine.cpp files then just implement the methods

#include "____.h"    
GameEngine::GameEngine() {

}

void GameEngine::run() {
    // stuff
}

However, I've recently read that variable declarations are not supposed to be in the header file. In the above example, that would be an inputManager and a, b, c.

Now, I've been searching for where to put the variable declarations, the closest answer I found was this: Variable declaration in a header file

However, I'm not sure if the use of extern would make sense here; I just declare private variables that will only be used in an instance of the class itself. Are my variable declarations in the header files fine? Or should I put them elsewhere? If I should put them in the cpp file, do they go directly under the #include?

like image 425
Kefir Avatar asked Feb 14 '15 16:02

Kefir


People also ask

Can you declare variables in header file C++?

Yes. Although this is not necessarily recommended, it can be easily accomplished with the correct set of macros and a header file. Typically, you should declare variables in C files and create extern definitions for them in header files.

How do you declare a class variable in cpp?

A class is defined in C++ using keyword class followed by the name of class. The body of class is defined inside the curly brackets and terminated by a semicolon at the end.

Do classes go in header files C++?

C++ classes (and often function prototypes) are normally split up into two files. The header file has the extension of . h and contains class definitions and functions.

What should be declared in a header file C++?

You make the declarations in a header file, then use the #include directive in every . cpp file or other header file that requires that declaration. The #include directive inserts a copy of the header file directly into the . cpp file prior to compilation.


1 Answers

Don't confuse a type's members with variables. A class/struct definition is merely describing what constitutes a type, without actually declaring the existence of any variables, anything to be constructed on memory, anything addressable.

In the traditional sense, modern class design practices recommend you pretend they are "black boxes": stuff goes in, they can perform certain tasks, maybe output some other info. We do this with class methods all the time, briefly describing their signature on the .h/.hpp/.hxx file and hiding the implementation details in the .cpp/.cc/.cxx file.

While the same philosophy can be applied to members, the current state of C++, how translation units are compiled individually make this way harder to implement. There's certainly nothing "out of the box" that helps you here. The basic, fundamental problem is that for almost anything to use your class, it kind of needs to know the size in bytes, and this is something constrained by the member fields and the order of declaration. Even if they're private and nothing outside the scope of the type should be able to manipulate them, they still need to briefly know what they are.

If you actually want to hide this information to outsiders, certain idioms such as PImpl and inlined PImpl can help. But I'd recommend you don't go this way unless you're actually:

  1. Writing a library with a semi-stable ABI, even if you make tons of changes.
  2. Need to hide non-portable, platform-specific code.
  3. Need to reduce pre-processor times due to an abundance of includes.
  4. Need to reduce compile times directly impacted by this exposure of information.

What the guideline is actually talking about is to never declare global variables in headers. Any translation unit that takes advantage of your header, even if indirectly, will end up declaring its own global variable as per header instructions. Everything will compile just fine when examined individually, but the linker will complain that you have more than one definition for the same thing (which is a big no-no in C++)

If you need to reserve memory / construct something and bind it to a variable's name, always try to make that happen in the source file(s).

like image 79
ZaldronGG Avatar answered Sep 19 '22 10:09

ZaldronGG