6

Instead of using #define or const, I usually define constants using class static methods as follows:

//AppConstants.h
#include <string>
class AppConstants{
public:
    static int getMax();
    static std::string getPrefix();
};

//AppConstants.cpp
#include "AppConstants.h"
int AppConstants::getMax(){
    return 30;
}

std::string AppConstants::getPrefix(){
    return "myprefix";
}

I do this usually when creating a mobile app, which I would like to save the compile time when each time change the value for testing. Is it a bad practice?

ggrr
  • 5,725
  • 11
  • 35
  • 37
  • 1
    that makes no sense. how exactly do you save compile time? – BЈовић Jun 29 '17 at 07:53
  • 2
    @BЈовић: When changing one of those constants, you only need to re-compile one file, instead of having to re-compile all files that reference one of the constants. – Bart van Ingen Schenau Jun 29 '17 at 09:51
  • 1
    @BartvanIngenSchenau depends where you put the constant. If it is in the source file, then you do not need to recompile. – BЈовић Jun 29 '17 at 11:33
  • 1
    I don't know that what you are doing is bad practice, per-se. But I think calling them "constants" is bad practice. Specifically, getMax cannot be used as a case in a switch statement or to specify the size of an array. Therefore, getMax is not a "constant". – OldFart Jun 29 '17 at 18:26

1 Answers1

12

Yes, and it's unnecessary too. You can declare constants in headers and define them in source files just like functions:

class AppConstants {
public:
  static const int Max;
  static const std::string Prefix;
};

const int AppConstants::Max = 30;
const std::string AppConstants::Prefix = "myprefix";

Especially in the case of the string, this has the advantage of not constructing a new one every time you access it.

It also has the disadvantage of being affected by C++'s unspecified global initialization order, so be careful if you use the constants from the initialization of other global variables/constants.

Sebastian Redl
  • 14,950
  • 7
  • 54
  • 51
  • 1
    While I mostly agree on this, why do you think it is a problem constructing a string every time? – BЈовић Jun 29 '17 at 08:17
  • 2
    It's an unnecessary heap allocation if the string is too long for SBO. – Sebastian Redl Jun 29 '17 at 08:21
  • it should allocate only if you modify the string - not otherwise – BЈовић Jun 29 '17 at 08:23
  • 1
    Converting a string literal to a std::string allocates unless the std::string employs the Small Buffer Optimization and the string is short enough to fit. Copy-on-Write strings are not allowed in C++11, and CoW only applies to std::string's copy constructor anyway, not the one that takes a character pointer. – Sebastian Redl Jun 29 '17 at 08:34
  • could use [operator""s](http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s) to avoid extra allocations – Caleth Jun 29 '17 at 08:34
  • 6
    @Caleth `operator""s` is a convenient syntactical shortcut, but it doesn't magically get rid of the allocations. If you really want to avoid allocations, you have to use `const std::string& getPrefix() { const static std::string prefix = "myprefix"; return prefix; }` – Sebastian Redl Jun 29 '17 at 08:36