[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

question on c++ constants?

shuisheng

10/14/2008 4:19:00 PM

Dear All,

I am always confused in using constants in multiple files.

For global constants, I got some clues from
http://msdn.microsoft.com/en-us/librar...(VS.80).aspx

So in header file writing: const double PI = 3.14;
Every time using it, include the header file.

But how about constants in namespaces and classes?

Thanks for your help!

Shuisheng
58 Answers

Victor Bazarov

10/14/2008 4:59:00 PM

0

shuisheng wrote:
> I am always confused in using constants in multiple files.
>
> For global constants, I got some clues from
> http://msdn.microsoft.com/en-us/librar...(VS.80).aspx
>
> So in header file writing: const double PI = 3.14;
> Every time using it, include the header file.
>
> But how about constants in namespaces and classes?

Yes, we use them too. What's the problem?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Ioannis Vranos

10/14/2008 5:07:00 PM

0

shuisheng wrote:
> Dear All,
>
> I am always confused in using constants in multiple files.
>
> For global constants, I got some clues from
> http://msdn.microsoft.com/en-us/librar...(VS.80).aspx
>
> So in header file writing: const double PI = 3.14;
> Every time using it, include the header file.
>
> But how about constants in namespaces and classes?
>
> Thanks for your help!
>
> Shuisheng



1. The easiest constants in classes are made by using enums:


#include <vector>

class SomeClass
{
enum { SIZE= 7 };

int array[SIZE];

std::vector<int> intVector;


public:
SomeClass(): intVector(5) {}
};



2. Regarding global constants and the header file you mentioned, in
simple words:

You can #include the header file with the global constant only in one
"implementation" file (e.g. .cpp) and to the rest implementation files
(e.g. .cpp), you can add the declaration:


extern const double PI;


==> In general avoid objects in the global namespace.





3. Regarding constants in namespaces, you have to include the definition
in the implementation file (e.g. by placing it in the header file).
file1.cpp:


E.g. pi.h:

namespace SomeNamespace
{
const double PI = 3.14;
}




What should be preferred instead of constants in the global namespace:

Constants (consts/enums) in anonymous namespaces (= local file scope
only), and constants (consts/enums) in named namespaces.


Regarding classes, you can either use static constants or (usually
better) enums.

Ioannis Vranos

10/14/2008 5:09:00 PM

0

Corrected:



shuisheng wrote:
> Dear All,
>
> I am always confused in using constants in multiple files.
>
> For global constants, I got some clues from
> http://msdn.microsoft.com/en-us/librar...(VS.80).aspx
>
> So in header file writing: const double PI = 3.14;
> Every time using it, include the header file.
>
> But how about constants in namespaces and classes?
>
> Thanks for your help!
>
> Shuisheng


1. The easiest constants in classes are made by using enums:


#include <vector>

class SomeClass
{
enum { SIZE= 7 };

int array[SIZE];

std::vector<int> intVector;


public:
SomeClass(): intVector(SIZE) {}
};



2. Regarding global constants and the header file you mentioned, in
simple words:

You can #include the header file with the global constant only in one
"implementation" file (e.g. .cpp) and to the rest implementation files
(e.g. .cpp), you can add the declaration:


extern const double PI;


==> In general avoid objects in the global namespace.





3. Regarding constants in namespaces, you have to include the definition
in the implementation file (e.g. by placing it in the header file).
file1.cpp:


E.g. pi.h:

namespace SomeNamespace
{
const double PI = 3.14;
}




What should be preferred instead of constants in the global namespace:

Constants (consts/enums) in anonymous namespaces (= local file scope
only), and constants (consts/enums) in named namespaces.


Regarding classes, you can either use static constants or (usually
better) enums.

Victor Bazarov

10/14/2008 5:21:00 PM

0

Ioannis Vranos wrote:
> Corrected:
> [..]
>
> Regarding classes, you can either use static constants or (usually
> better) enums.

Well, there aren't double or string enums, so... The difference between
the class [non-integral] constants and the namespace ones is that the
class constants have to be declared in the class and *defined* in some
translation unit, while the namespace constants can be defined in the
header (which means they will be duplicated in every translation unit
that includes the header), which is OK because they have internal
linkage (unless you specify otherwise).

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

shuisheng

10/14/2008 8:31:00 PM

0

On Oct 14, 1:20 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
> Ioannis Vranos wrote:
> > Corrected:
> > [..]
>
> > Regarding classes, you can either use static constants or (usually
> > better) enums.
>
> Well, there aren't double or string enums, so...  The difference between
> the class [non-integral] constants and the namespace ones is that the
> class constants have to be declared in the class and *defined* in some
> translation unit, while the namespace constants can be defined in the
> header (which means they will be duplicated in every translation unit
> that includes the header), which is OK because they have internal
> linkage (unless you specify otherwise).
>
> V
> --
> Please remove capital 'A's when replying by e-mail
> I do not respond to top-posted replies, please don't ask

So I think the following is the right way, please confirm it. I use PI
as an example.

For global constants:

// in constants.h
const double PI = 3.14;

// in h or cpp files to use PI
#include "constants.h"
double a = PI;


For constants in namespace:

// in constants.h
namespace constants
{
const double PI = 3.14;
};

// in h or cpp files to use PI
#include "constants.h"
double d = constants::PI;


For constants in classes:

// in class.h
class A
{
public:
static const double PI;
};

// in class.cpp
const double A::PI = 3.14;

// in h and cpp files to use it.
#include "class.h"
double a = A::PI;

And I think Ioannis Vranos's way to define global constants will bring
about problems as shown in http://msdn.microsoft.com/en-us/librar...(VS.80).aspx

Thanks and best regards,

Victor Bazarov

10/14/2008 8:58:00 PM

0

shuisheng wrote:
> [..]
> So I think the following is the right way, please confirm it. I use PI
> as an example.
>
> For global constants:
>
> // in constants.h
> const double PI = 3.14;
>
> // in h or cpp files to use PI
> #include "constants.h"
> double a = PI;
>
>
> For constants in namespace:
>
> // in constants.h
> namespace constants
> {
> const double PI = 3.14;
> };
>
> // in h or cpp files to use PI
> #include "constants.h"
> double d = constants::PI;
>
>
> For constants in classes:
>
> // in class.h
> class A
> {
> public:
> static const double PI;
> };
>
> // in class.cpp
> const double A::PI = 3.14;
>
> // in h and cpp files to use it.
> #include "class.h"
> double a = A::PI;
>
> And I think Ioannis Vranos's way to define global constants will bring
> about problems as shown in http://msdn.microsoft.com/en-us/librar...(VS.80).aspx

The code you showed here is perfectly fine, and you can declare/define
any constants that way, not just of fundamental types, AFAIC.

The contents of the web page you cited do bother me. I am not sure what
"static linkage" is; there is no such term in C++ Standard. Why would
the page say that "If you try to use a global constant in C++ in
multiple files you get an unresolved external error"? What kind of
nonsense is that? If you *do* declare some object "extern", then you
must define it somewhere. If you don't defined it, you violate the ODR.

The point in using constants like you've shown is that there *is* a
*defined* object in every module, it has internal linkage (since it's
declared 'const' and does not have external linkage), and that's it.
Whether those objects are "optimized out" does not matter. From the
language point of view they exist, have value, are constant, and that's
about all we need to know.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

shuisheng

10/14/2008 9:42:00 PM

0

On Oct 14, 4:58 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
> shuisheng wrote:
> > [..]
> > So I think the following is the right way, please confirm it. I use PI
> > as an example.
>
> > For global constants:
>
> >   // in constants.h
> >   const double PI = 3.14;
>
> >   // in h or cpp files to use PI
> >   #include "constants.h"
> >   double a = PI;
>
> > For constants in namespace:
>
> >   // in constants.h
> >   namespace constants
> >   {
> >     const double PI = 3.14;
> >   };
>
> >   // in h or cpp files to use PI
> >   #include "constants.h"
> >   double d = constants::PI;
>
> > For constants in classes:
>
> >   // in class.h
> >   class A
> >   {
> >   public:
> >     static const double PI;
> >   };
>
> >   // in class.cpp
> >   const double A::PI = 3.14;
>
> >   // in h and cpp files to use it.
> >   #include "class.h"
> >   double a = A::PI;
>
> > And I think Ioannis Vranos's way to define global constants will bring
> > about problems as shown inhttp://msdn.microsoft.com/en-us/librar...(VS.80).aspx
>
> The code you showed here is perfectly fine, and you can declare/define
> any constants that way, not just of fundamental types, AFAIC.
>
> The contents of the web page you cited do bother me.  I am not sure what
> "static linkage" is; there is no such term in C++ Standard.  Why would
> the page say that "If you try to use a global constant in C++ in
> multiple files you get an unresolved external error"?  What kind of
> nonsense is that?  If you *do* declare some object "extern", then you
> must define it somewhere.  If you don't defined it, you violate the ODR.
>
> The point in using constants like you've shown is that there *is* a
> *defined* object in every module, it has internal linkage (since it's
> declared 'const' and does not have external linkage), and that's it.
> Whether those objects are "optimized out" does not matter.  From the
> language point of view they exist, have value, are constant, and that's
> about all we need to know.
>
> V
> --
> Please remove capital 'A's when replying by e-mail
> I do not respond to top-posted replies, please don't ask

I tested using "extern" as following in visual studio 2005.

//! in constants.h
extern const double PI;

//! in constants.cpp
const double PI = 3.14;

When using for multiple files, especially when PI is defined in a
library, it gives a link error. I think C++ treats global constants
different from global non-constant variables. My understanding is
that: there is no external objects somewhere for global constants,
even in "constants.cpp" having the code "const double PI = 3.14;".

Ioannis Vranos

10/14/2008 9:50:00 PM

0

shuisheng wrote:
>
> So I think the following is the right way, please confirm it. I use PI
> as an example.
>
> For global constants:
>
> // in constants.h
> const double PI = 3.14;
>
> // in h or cpp files to use PI
> #include "constants.h"
> double a = PI;


This is OK, but try not polluting the global namespace.



>
> For constants in namespace:
>
> // in constants.h
> namespace constants
> {
> const double PI = 3.14;
> };
>
> // in h or cpp files to use PI
> #include "constants.h"
> double d = constants::PI;


There are also the anonymous namespaces which have local file scope:


namespace
{
const double PI= 3.14;
};



> For constants in classes:
>
> // in class.h
> class A
> {
> public:
> static const double PI;
> };
>
> // in class.cpp
> const double A::PI = 3.14;
>
> // in h and cpp files to use it.
> #include "class.h"
> double a = A::PI;


or enums for integer constants.



> And I think Ioannis Vranos's way to define global constants will bring
> about problems as shown in http://msdn.microsoft.com/en-us/librar...(VS.80).aspx


Yes you are right. This is one of the differences between C++ and C.

Victor check TC++PL3 on page 200.


const int x= 7; in global scope is equivalent to

static const int x= 7;


For this to work as C, definition must be accompanied with the word
extern, that is:


extern const double PI= 3.14;


But as I said, we must avoid global variables as much as possible and
must avoid polluting the global namespace as much as possible.

Ioannis Vranos

10/14/2008 9:57:00 PM

0

Recorrected:


shuisheng wrote:
> Dear All,
>
> I am always confused in using constants in multiple files.
>
> For global constants, I got some clues from
> http://msdn.microsoft.com/en-us/librar...(VS.80).aspx
>
> So in header file writing: const double PI = 3.14;
> Every time using it, include the header file.
>
> But how about constants in namespaces and classes?
>
> Thanks for your help!
>
> Shuisheng


Corrected:



shuisheng wrote:
> Dear All,
>
> I am always confused in using constants in multiple files.
>
> For global constants, I got some clues from
> http://msdn.microsoft.com/en-us/librar...(VS.80).aspx
>
> So in header file writing: const double PI = 3.14;
> Every time using it, include the header file.
>
> But how about constants in namespaces and classes?
>
> Thanks for your help!
>
> Shuisheng


1. The easiest constants in classes are made by using enums:


#include <vector>

class SomeClass
{
enum { SIZE= 7 };

int array[SIZE];

std::vector<int> intVector;


public:
SomeClass(): intVector(SIZE) {}
};



2. Regarding global constants and the header file you mentioned, in
simple words:

i) You can #include the header file (e.g .h) in all implementation files
(e.g. .cpp), keeping in mind that as a result, each instance of the
constant (defined as const double PI= 3.14;) is a different file-scope
(more accurately, compilation unit - scope) object.


ii) You can #include the header file with the global constant in the form:


extern const double PI= 3.14;


in one "implementation" file (e.g. .cpp) and to the rest implementation
files (e.g. .cpp), you can add the declaration:


extern const double PI;




==> In general avoid objects in the global namespace.



3. Regarding constants in namespaces, you have to include the definition
in the implementation file (e.g. by placing it in the header file).


E.g. pi.h:

namespace SomeNamespace
{
const double PI = 3.14;
}




What should be preferred instead of constants in the global namespace:

Constants (consts/enums) in anonymous namespaces (= local file scope
only), and constants (consts/enums) in named namespaces.


Regarding classes, you can either use static constants or (usually
better) enums.

Victor Bazarov

10/14/2008 10:05:00 PM

0

shuisheng wrote:
> On Oct 14, 4:58 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
>> shuisheng wrote:
>>> [..]
>>> So I think the following is the right way, please confirm it. I use PI
>>> as an example.
>>> For global constants:
>>> // in constants.h
>>> const double PI = 3.14;
>>> // in h or cpp files to use PI
>>> #include "constants.h"
>>> double a = PI;
>>> For constants in namespace:
>>> // in constants.h
>>> namespace constants
>>> {
>>> const double PI = 3.14;
>>> };
>>> // in h or cpp files to use PI
>>> #include "constants.h"
>>> double d = constants::PI;
>>> For constants in classes:
>>> // in class.h
>>> class A
>>> {
>>> public:
>>> static const double PI;
>>> };
>>> // in class.cpp
>>> const double A::PI = 3.14;
>>> // in h and cpp files to use it.
>>> #include "class.h"
>>> double a = A::PI;
>>> And I think Ioannis Vranos's way to define global constants will bring
>>> about problems as shown inhttp://msdn.microsoft.com/en-us/librar...(VS.80).aspx
>> The code you showed here is perfectly fine, and you can declare/define
>> any constants that way, not just of fundamental types, AFAIC.
>>
>> The contents of the web page you cited do bother me. I am not sure what
>> "static linkage" is; there is no such term in C++ Standard. Why would
>> the page say that "If you try to use a global constant in C++ in
>> multiple files you get an unresolved external error"? What kind of
>> nonsense is that? If you *do* declare some object "extern", then you
>> must define it somewhere. If you don't defined it, you violate the ODR.
>>
>> The point in using constants like you've shown is that there *is* a
>> *defined* object in every module, it has internal linkage (since it's
>> declared 'const' and does not have external linkage), and that's it.
>> Whether those objects are "optimized out" does not matter. From the
>> language point of view they exist, have value, are constant, and that's
>> about all we need to know.
>>
>> V
>> --
>> Please remove capital 'A's when replying by e-mail
>> I do not respond to top-posted replies, please don't ask
>
> I tested using "extern" as following in visual studio 2005.
>
> //! in constants.h
> extern const double PI;
>
> //! in constants.cpp
> const double PI = 3.14;

This 'PI' and the 'PI' you declared in the header are two different pies
(so to speak). One has external linkage because you told it to have it
by using 'extern', the other has internal linkage because you declared
it 'const' and didn't specify any linkage and by default it's internal.

The fix for that is

//! in constants.cpp
extern const double PI = 3.14;

or

//! in constants.cpp
#include "constants.h"
const double PI = 3.14;

> When using for multiple files, especially when PI is defined in a
> library, it gives a link error. I think C++ treats global constants
> different from global non-constant variables. My understanding is
> that: there is no external objects somewhere for global constants,
> even in "constants.cpp" having the code "const double PI = 3.14;".

I don't understand your understanding, sorry. If you intend to refer to
the same object from anywhere in your code, you need to make sure that
you declare it *the same way* everywhere.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask