C++ How to share constants with extern between cpp

2019-08-12 02:27发布

问题:

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'?

回答1:

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!



回答2:

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;