1

I've the header file in which I declare some constants with extern:

#ifndef CONSTANTS_H
#define CONSTANTS_H

#include <string>

class Constants
{
    public:
        Constants(){}
        extern const std::string DELIMITER;
        extern const std::string FILENAME;
        extern const int BLUCAR;
        extern const int REDCAR;
        extern const int EMPTY;
        extern const int SPARSE_LIM;
    protected:
    private:
};

#endif // CONSTANTS_H

Then in the source I define them like this:

#include "constants.h"

extern const std::string DELIMITER = ",";
extern const std::string FILENAME = "cars.csv";
extern const int BLUCAR = 1;
extern const int REDCAR = 2;
extern const int EMPTY = 0;
extern const int SPARSE_LIM = 5;

Why the compiler gives me Error: storage class specified for 'DELIMITER'?

rh0x
  • 1,066
  • 1
  • 13
  • 33
  • Deleting the class definition, constructor and the access modifiers the error is solved. Is it the right way? – rh0x Jan 03 '16 at 16:53

2 Answers2

4

Firstly, these don't seem to be class members. The way you're using extern it looks like you intended for these to be free. Perhaps in a namespace. Take them out of that class.

Then, when you define them, leave out the extern.

In this context it means "find this variable elsewhere". You don't want to find it elsewhere. It's here!

// Header
namespace Constants {
   extern const std::string DELIMITER;
   extern const std::string FILENAME;
   extern const int         BLUCAR;
   extern const int         REDCAR;
   extern const int         EMPTY;
   extern const int         SPARSE_LIM;
}


// Source
namespace Constants {
   const std::string DELIMITER  = ",";
   const std::string FILENAME   = "cars.csv";
   const int         BLUCAR     = 1;
   const int         REDCAR     = 2;
   const int         EMPTY      = 0;
   const int         SPARSE_LIM = 5;
}

Remember, you'd do the same for static object definitions!

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • I understand what you say, but I need to define them in the source file so that I can include the header file in which they are only declared. In that way when I modify a value, the files in which constants.h is included don't need to be recompiled. I don't know if what I'm saying is right, but I understood that here: http://stackoverflow.com/questions/9649405/c-best-practices-for-constants – rh0x Jan 03 '16 at 16:57
  • @rh0x: Yes, define them in the source file. I showed you how. – Lightness Races in Orbit Jan 03 '16 at 16:59
3

I think you either want to use static members in your class, use a namespace instead of a class, or put your constants in the global namespace.

For static members:

class Constants
{
    public:
        Constants(){}
        static const std::string DELIMITER;
        static const std::string FILENAME;
        static const int BLUCAR;
        static const int REDCAR;
        static const int EMPTY;
        static const int SPARSE_LIM;
    protected:
    private:
};

and in your source file

const std::string Constants::DELIMITER = ",";
const std::string Constants::FILENAME = "cars.csv";
const int Constants::BLUCAR = 1;
const int Constants::REDCAR = 2;
const int Constants::EMPTY = 0;
const int Constants::SPARSE_LIM = 5;

However, it looks like your class is more like a namespace than a class, since there would be no point in making instances.

But there is another option. You may not even want to use a class or a namespace, but just have them all in the global namespace:

// header
extern const std::string DELIMITER;
extern const std::string FILENAME;
extern const int BLUCAR;
extern const int REDCAR;
extern const int EMPTY;
extern const int SPARSE_LIM;

// source
const std::string DELIMITER = ",";
const std::string FILENAME = "cars.csv";
const int BLUCAR = 1;
const int REDCAR = 2;
const int EMPTY = 0;
const int SPARSE_LIM = 5;
Vaughn Cato
  • 63,448
  • 5
  • 82
  • 132
  • Yes, you are right! As also 'Lightness Races in Orbit' says probably the best option is to use a namespace. Thank you! – rh0x Jan 03 '16 at 17:04
  • 1
    @rh0x: Note that you only need a namespace if you want to group them in some way, such that you use your namespace prefix for access. If you just want to be able to use `DELIMITER` instead of `Constants::DELIMITER`, then putting it in the global namespace may be what you want. – Vaughn Cato Jan 03 '16 at 17:06