0

So I'm currently working on a school-project with C++, which I'm not really familiar with. I would like to create a class, containing all my constants (string,int,double,own classes) I was trying this, which has always worked for me in Java:

class Reference {


    //Picture-Paths
    public:
    static const std::string deepSeaPath = "E:\\Development\\C++\\Material\\terrain\\deep_sea.tga";
    static const std::string shallowWaterPath = "E:\\Development\\C++\\Material\\terrain\\deep_sea.tga";
    static const std::string sandPath = "E:\\Development\\C++\\Material\\terrain\\deep_sea.tga";
    static const std::string earthPath = "E:\\Development\\C++\\Material\\terrain\\deep_sea.tga";
    static const std::string rocksPath = "E:\\Development\\C++\\Material\\terrain\\deep_sea.tga";
    static const std::string snowPath = "E:\\Development\\C++\\Material\\terrain\\deep_sea.tga";

};

In C++, however, I get the following error:

Error   C2864   'Reference::Reference::earthPath': a static data member with an in-class initializer must have non-volatile const integral type bio-sim-qt  e:\development\c++\bio-sim-qt\bio-sim-qt\Reference.hpp  16  1   

So is there any way for me to store for example String-Constants like this? If yes, is there even a better way to do it? If no, is there another way (#define?) ?


Awesome36
  • 89
  • 7
  • 1
    If all you're having in your class are public static member variables (or public static member functions) then I suggest using a namespace instead. – Some programmer dude Jun 12 '17 at 09:45
  • 1
    As for your problem, only put the *declarations* in the class (or namespace), then put the *definitions* (with their initialization) in a source file. – Some programmer dude Jun 12 '17 at 09:46

2 Answers2

5

In C++17, the recommended way of defining string constants if by using an inline constexpr std::string_view. Example:

namespace reference
{
    inline constexpr std::string_view deepSeaPath{R"(something)"};
    // ...
}

This is great because:

  • std::string_view is a lightweight non-owning wrapper that can efficiently refer to string literals without any additional costs.

  • std::string_view seamlessly interoperates with std::string.

  • Defining the variables as inline prevents ODR issues.

  • Defining the variables as constexpr makes it clear to both the compiler and other developers that these are constants known at compile-time.


If you do not have the luxury of using C++17, here's a C++11 solution: define your constants as constexpr const char* in a namespace:

namespace reference
{
    constexpr const char* deepSeaPath{R"(something)"};
    // ...
}
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
1

You should declare your data members in your header file, but the definitions should be placed in the source file, like this for example:

const std::string Reference ::earthPath = "E:\\Development\\C++\\Material\\terrain\\deep_sea.tga";

Read more in: Static Data Member Initialization.


PS: Classes do not use to expose into public scope their data members. Getter and Setter functions are used instead, while the data members are not in public scope. If all you need is your data members, then a namespace could be a better design choice, than a class.

gsamaras
  • 71,951
  • 46
  • 188
  • 305