Jump to content

  • Log In with Google      Sign In   
  • Create Account


#Actuale‍dd

Posted 23 November 2012 - 10:49 PM

Simply write this in your header file, and nothing in the .cpp file:

const int MAX_INTS = 1000;


That will of course solve the problem, but for the OP's benefit I think it might be worth giving a little more background on why 'extern' isn't needed here.

For example, you can't put "int MAX_INTS = 1000;" in a header file without opening yourself up to ODR violations, despite the trivial visual differences between this definitions and "const int MAX_INTS = 1000;".

Muddying the waters further are differences in semantics between C and C++.

In C++, a definition such as "const int MAX_INTS = 1000;" defines the MAX_INT object with internal linkage. This means that if the definition resides within a header, and that header is #included in to multiple translation units, you're really creating a number of distinct objects (though I think a linker could still put them all at the same location in the end, as a space optimization).

However, "int MAX_INTS = 1000;" defines an object with external linkage because MAX_INTS is not const. This means that if this definition resides within a header, and that header is #included in to multiple translation units, you're defining a single object multiple times. This is an ODR (one definition rule) violation, which says (approximately) that objects with external linkage must have a single definition across the entire program. So in this case, the correct thing to do is indeed to declare MAX_INTS with 'extern' in a header, and then define it in a single translation unit.

In C, everything we've seen so far has external linkage. If you want to put a constant in a header, you either use a #define instead, or put 'static' in front of the definition to give each copy of the variable internal linkage within their respective translation units. You can also use 'static' in the C++ definitions too without causing harm, except for the redundant keyword.

There are some other rules too, making the whole subject quite intricate. But the important things to understand are the concepts of internal and external linkage. Knowledge about how and when definitions and declarations affect linkage will come with time and practice.

(Edited to remove incorrect stuff about floats).

#1e‍dd

Posted 23 November 2012 - 10:34 PM

Simply write this in your header file, and nothing in the .cpp file:

const int MAX_INTS = 1000;


That will of course solve the problem, but for the OP's benefit I think it might be worth giving a little more background on why 'extern' isn't needed here.

For example, prior to C++11 you can't put either "const float MAX_AMPLITUDE = 14.7F;" or "int MAX_INTS = 1000;" in a header file without opening yourself up to ODR violations, despite the trivial visual differences between these definitions and "const int MAX_INTS = 1000;".

Muddying the waters further are differences in semantics between C, C++98 and C++11.

In C++98, a definition such as "const int MAX_INTS = 1000;" defines the MAX_INT object with internal linkage. This means that if the definition resides within a header, and that header is #included in to multiple translation units, you're really creating a number of distinct objects (though I think a linker could still put them all at the same location in the end, as a space optimization).

However, still in C++98 land, "const float MAX_AMPLITUDE = 14.7F;" defines an object with external linkage because MAX_AMPLITUDE is not of an integral type. This means that if this definition resides within a header, and that header is #included in to multiple translation units, you're defining a single object multiple times. This is an ODR (one definition rule) violation, which says (approximately) that objects with external linkage must have a single definition across the entire program. So in this case, the correct thing to do is indeed to declare MAX_AMPLITUDE with 'extern' in a header, and then define it in a single translation unit.

In C++11, I am under the impression that const floats now have internal linkage, meaning "const float MAX_AMPLITUDE = 14.7F;" can now be safely placed in a header (given a suitably modern compiler with an appropriate configuration), though I am not sure about this. I think there's also some interaction with constexpr, though I'm not at all well-read on that stuff.

In all versions of C++, a definition such as "int MAX_INTS = 1000;" also declares an object with external linkage, because of the lack of 'const'. So don't do this in a header.

In C, everything we've seen so far has external linkage. If you want to put a constant in a header, you either use a #define instead, or put 'static' in front of the definition to give each copy of the variable internal linkage within their respective translation units. You can also use 'static' in the C++ definitions too without causing harm, except for the redundant keyword.

There are some other rules too, making the whole subject quite intricate. But the important things to understand are the concepts of internal and external linkage. Knowledge about how and when definitions and declarations affect linkage will come with time and practice.

PARTNERS