restricting scope of variables in headers - c++

I have a multi-file program consisting of
main.cpp
ext1.cpp
ext2.cpp
ext3.cpp
vars.h
As the name suggests, main.cpp is the main file, extX.cpp contains various functions and vars.h some global constants.
However, in main.cpp there are also (a few!) variable declarations, but they must only be within the scope of main.cpp -- that is why I haven't placed them in vars.h
I want to reduce the amount of code in main.cpp (for clarity-issues). I am looking for a way to declare these variables inside a header of some sort, but in a way that it is only visible to main.cpp.
Is it correctly understood that if I place them all inside e.g. vars_main.h (with no external keyword) and just include "vars_main.h", then I have achieved my goal?
Is it considered to be "correct" C++-style to do it this way?

If those variables are used only in main(), then yes, you could do that. But I would not go as far as considering it a "correct C++ style".
If one day you will end up including that header file into another translation unit (maybe because you will need to share just one of those variables), the linker will start complaining about multiple definitions.
At that point, to overcome this, you could use the static keyword to give those variables internal linkage and workaround the problem of multiple definitions. This way, however, each translation unit (.cpp file) will hold its own copy of those variables, which is probably not what you want, especially if they are not constant - just for the record, global constants have internal linkage by default, so you won't need to explicitly qualify them as static.
The normal practice here is either to leave those variable definitions in main(), or to have one header which contains only extern declarations of those variables, and one translation unit that contains their definitions. Then, all the files which need to access those variable would just import the header with the declarations.

The usual practice would be to go ahead and define them in main.cpp, since they're in a distinct block and won't affect the readability of the code. However you can certainly move them out to a separate include file that's only included in one .cpp, that's a stylistic choice that's completely up to you.

If the variables you are talking about are global variables private to main, I think that you should let them in main.cpp. If they are not used anywhere else, it does not make sense to declare them in a header
You could also create a class implementing the "main" features with your variables in private scope so that they won't be used by other parts of the implementation .

Related

Are static or unnamed namespace still useful when header and implementation are separated?

As answered in this question, I learnt that the static keyword to the function means it can only be seen from the functions in that file. I think unnamed namespace can be used for the same purpose.
However, usually, implementation and header files are separated. So, it seems to me that a programmer can hide all the "private stuff" inside the implementation file by not writing the declaration of such private stuff in the header file.
Considering above, when are static and unnamed namespaces helpful? The only case I can come up with is where multiple implementation files correspond to a single header file.
Keeping a definition in implementation file does not make it private in any sense. Any other header or implementation file can declare that function and use it. It's not always a bad thing - I used parts of private implementations of libraries when I really needed it (but I do not recommend doing that).
The worse part of having such not-so-private implementation is its potential for One Definition Rule violation. ODR states that every* function or variable must have exactly one definition in the whole program. If there is more than one definition, behaviour is undefined**.
This means that when you have your not-so-private implementation in your file and nobody knows about it, they can unknowingly write a function with the same name and arguments and get an ODR violation.
It would be a good practice to use static or anonymous namespace for all free functions that should be limited to a single file. Functions that need to be used from other files cannot use this strategy, so to limit the risk of ODR violations you should use descriptive names and perhaps (named) namespaces. Just make sure you don't overuse namespaces.
Note: using anonymous namespaces doesn't make sense in header files. Anonymous namespace limits the scope of its content to the translation unit in which it exists, but header files are copied and pasted into (potentially) multiple TUs. The one use of anonymous namespaces is in header-only libraries, as described in this question - it allows to create global objects in header file without ODR violation (but at a cost that each TU has its own copy of that variable).
*except for template functions, inline functions, functions defined in class definition and a couple more. Even then, all definitions must be exactly the same.
**When I encountered it once, linker used random definition, whichever it saw at that moment. Hilarity and long debugging sessions ensued.

Includes causing problems in c++. How to learn to do c++ right

So I have made a complex project and now I have too many include files causing me headaches. How can I best manage these classes? Some classes need to use other classes. I also have a .h file containing a bunch of arrays of int. These stay the same through the application but I get the problem when the compiler complains that I am redefining the array.
Should I make a class library? Namespace? DLL? What is the best practice and where can I find out how to do the right one?
Use include guards in all your headers.
file.h
#ifndef FILE_H_INCLUDED
#define FILE_H_INCLUDED
void foo();
#endif
Avoid global variables when possible. If you must use them, declare global variables using extern and place the definition in a .cpp file instead.
file.h
extern int var[20];
file.cpp
int var[20];
When possible, use forward declarations. You can use forward declarations whenever you use only a reference or a pointer to a class and don't dereference that pointer.
useful.h
class Useful {};
other.h
// Forward-declare instead of #include
class Useful;
class Other
{
Useful* helper;
};
I don't think there really is a best practice, it depends on the situation. Something I might recommend is to group like objects into a namespace then put all of the definitions in a single .h file. If the implementations are short, put them all in a single cpp file. Here at my work we have a database access layer like this. There are roughly a couple dozen objects that are populated by stored procs. The code is still a major pain in the ass but it's better than having two dozen .h and cpp files that are all less than 500 lines. If you do this comments to compartmentalize object definitions become really important. You can easily get files longer than 10,000 lines so you need something to break them up.
Of course use include guards, they'll likely solve the redefining error.
You need to know the difference between a definition and a declaration, and what uses of an entity required the entity to be declared. Then you also need to learn the 'one definition rule' (ODR) which tells you when when you're not allowed to have more than one definition in the program (and therefore the definition can't go in a header) and what things can be defined more than once as long as the definitions are identical (and therefore the definition can go in a header).
For example, those arrays you're declaring; since these are globally visible arrays the program can only contain one definition, and therefore the definition can't go in a header. Every part of the program that needs to access them simply needs to know their declaration. So instead of putting a definition in a header file and violating the ODR, you should have a C++ file that contains their definition and a header that contains declarations for them.
Code like this:
int foo[100];
both declares and defines the array foo. Put code like this in a C++ file. To only declare this array you do this:
extern int foo[100];
Put code like this in a header.
Class definitions, inline functions, and templates are all things that can be defined multiple times as long as the definitions are identical. You can put these definitions into headers, whereas regular functions, and global variables may only be defined once, so you declare them in headers and then define them in implementation files.

How to "hide" a variable inside the header file?

The header file contains two variables.
Because of the structure of my program, I have two "ld: duplicate symbol" errors.
These two variables have only local significance.
Is there any way of making these variables "private", so they wouldn't be seen outside of the header file even if the header file is included to another source file?
EDIT: please tell me, would it be nice if I will put the variables to the cpp file? These variables are very big arrays, defined while initializing, and take a lot of lines of code...
extern char Lookup[][3] = { "aa", "ab", "ac", "ad", "ae", "af", ... and so on (really long)}
The solution is to not define variables in your header file.
If you absolutely must share variables between internal source files (and I recommend that you don't), then you should do the following:
Create an "internal.h".
Declare your variable extern in that header file.
Include "internal.h" in both your internal source files.
Define the variable in one or other internal source files.
The variable is now hidden from the outside world. (It's probably still visible in your object files, but you can use platform-specific trickery to strip it.)
Do not define variable in headers.
Use extern to declare a variable in a header without defining it.
I'm always weary about variables which are "on the loose". I mean: they do affect something don't they? They "belong" to a class?
Shouldn't you just declare them under a class, and then declare them as static variables? (And given the syntax, probably constants too)? In that case you can simply use everything normally done with static variables (initializer lists, static initialize function etc). Seems to me much more clearer, as now your variable is tied with something.

extern pointer problem in c++

I have a header file that has a number of declarations like this:
extern ID3D10Device* device;
I can't make these static because of a problem with multiple translation units, and I can't have them as normal pointers for a similar reason. However when I try to build the program I get unresolved external symbol linker errors. I'm assuming that this is because I'm attempting to use the pointers without defining them first. This is the problem however, as the way you initialise these DirectX objects is by passing the address of the pointers as parameters into specialist methods. - I may be wrong but I am assuming this is the problem as the compiler / linker / whatever can't see the definitions.
All I'm trying to do is have these pointers (for the graphics device, depth buffer etc) visible to multiple classes. How can this be achieved?
You need the pointers to be defined in some translation unit. The linker is complaining because it seems you haven't done that anywhere. You should declare them at file scope as
ID3D10Device* device = NULL;
in the source file where you call the DirectX function that initializes them. Just make sure the declaration is only made in one source file, then the extern statement should be placed in the associated header file which is included by all translation units that need to use these pointers.
When you externally define a variable like this, the compiler is not reserving any memory for that variable until it sees a definition inside a code module itself. So if you are going to be passing these pointers by-reference to a function for initializing their values, they must be defined in a code module somewhere.
You only need to define them in a single code module ... then place the extern declarations inside a header file you include in the rest of your code modules that require access to the pointer variables. That shouldn't create any linker errors due to duplicate definitions.
I can't make these static because of a problem with multiple translation units
If you need a different variable in different TU (translation units), make it static: this way the variable will be specific to each TU.
A declaration of a variable is also definition unless the extern is used.
You must have one (and only one) definition of a variable in the program.
To have a global variable:
Declare it with the extern keyword in some header file.
Include this header in every TU that needs to use the variable. Never declare the variable directly, never bypass the header inclusion.
Define the variable: a declaration without the extern keyword will define the variable in one TU. You need to include the header file in the same TU to guaranty consistency between the extern declaration and the definition.
the way you initialise these DirectX objects is by passing the address
of the pointers as parameters into specialist methods
To solve this part of the problem, you could do something like this (in a .cpp file):
ID3D10Device* device;
struct Foo {
Foo(ID3D10Device **pdevice) { specialist_method(pdevice); }
};
Foo f(&device);
Beware of the "static initialization order fiasco", though -- it's safe to use device from main, or code called from main, because it will definitely be initialized before that code executes. It's not necessarily safe to use it from other initializers executed before main, because the order of initialization of statics in different translation units is unspecified (within a TU, they're initialized in order of either declaration or definition, I forget which). So device might still be a null pointer in that code. Likewise, specialist_method can't necessarily rely on other statics having been initialized.
There are extra tricks you can use if you need to enforce initialization orders, I'd guess that all the common ones are on SO already in other questions.

Define global variable as hash

I have a number of C++ classes, alot of them (not all) share two "static size variables" e.g.
share.h
/*Other variables in this header used by all classes*/
static size width=10;//Used by about 60%
static size height = 12;//used by about 60%
So I placed them in a header file along with other objects that all classes share.
when I compile the project I get alot of warnings (from the classes which dont use these), which complain about them being defined and not used. But I need them there!
So I ask, is there a way to hash these to prevent such warnings?
Hashing them so that they can be defined! preventing warnings from classes calling this header file which dont require these last two variables, but they call header because they need everything else init
You should place them in an individual header file. So you can include it only in the classes they need it. This avoids the warning in the other classes. So in the end you will have two header files. One where the stuff for all classes is included and another where the variables which are not used in all are defined.
However try to avoid global variables.
Edit reading tune2fs' answer, I realized I may have interpreted the question wrong.
Perhaps you forgot to use extern in the header file? If you just include static definitions in the header file all compilation units will have unique copies, not shared. See also this explanation of static/extern
Edit Disambiguated in comments
static SomeClass NotUnusedInstance;
static void unused_vars_helper()
{
static SomeClass* take_address = &NotUnusedInstance;
}
This approach is design to have minimal impact (not invoking any actual code; take_address isn't actually initialized unless you call unused_vars_helper).
This should work pretty well for your case. You can make unused_vars_helper() static and/or move it inside an anonymous namespace to prevent external visibility of the helper.