Search code examples
c++compiler-errorsconstantsheader-filesextern

C++: implementing a global constant whose value is given by the user


First of all, let me say I have read similar threads on how to initialize a global variable or how to properly implement global constants. Nevertheless, these questions did not really help me with my concrete problem, as also haven't any other ressources I've consulted. The problem is the following.

I (have to) declare in a header file header.h a variable that must be constant and used by the main function in main.cpp as well as other functions defined in a another file functions.cpp (that are previously declared in header.h). The problem is this constant is a runtime constant, whose value is given by the user. How should I proceed?

I think my best shot was to do as follows. In header.h

// Header guard

namespace n
{
    // Some forward declarations

    extern const double mu; // The constant that should be initialized by the user.

    // Some other declarations
}

then in functions.cpp

#include "header.h"

namespace n
{
    // Some definitions here

    double function_that_uses_mu(double a, double b)
    {
        // Some code using mu

        return somedouble;
    }

    // Some other definitions
}

finally main.cpp

#include "header.h"
#include <iostream>

int main()
{
    // Some code

    double value_of_mu{};
    std::cin >> value_of_mu;        
    // Validity check
    extern const double n::mu{ value_of_mu };

    // More code

    return 0;
}

The problem is that compilation fails due to the fact that error: ‘mu’ has both ‘extern’ and initializer. However, if I tried mu = value_of_mu I would obviously get an error because I would be assigning to a const value (not initialising it). So I don't know how to proceed, or what's wrong with my code. There are two mandatory facts I must respect:

  1. Functions/global-consts definitions, functions/global-consts declarations and main must be split in the three aforementioned files.

  2. mu is to be defined as a constant shared by all three files.

Is this possible? How?

EDIT:

I think my problem is that an exten variable can't be initialised inside a function, but if this is so, I don't see how I do what I'm trying to.


Solution

  • Think about it: If a value needs to be set during the lifetime of a program, it's not really a constant. So, you shouldn't try to pretend it's a constant by declaring it as const. If you don't want the program to accidentally change its value, you have to protect it in some other way, such as making it a private member variable of a class. That way, you can restrict access to only return the value of mu as a const.

    // muholder.h
    
    class muholder
    {
     private:
        double m_value;
     public:
        muholder (double ivalue): m_value(ivalue) {}
        double const &value() const { return m_value; }
    };
    
    // workflow_envelope.h
    
    class workflow_envelope
    {
        private:
        muholder m_mu;
    
        public:
        workflow_envelope (double imu): m_mu(imu) {}
        bool validity_check();
        double method_that_uses_mu (double a, double b) const  { return a*m_mu.value()/ b; }
        void run(); // any "more code" goes in here. 
    };
    
    // main
    #include "workflow_envelope.h"
    #include <iostream>
    
    int main()
    {
        // Some code
    
        double value_of_mu;
        if (std::cin >> value_of_mu)
        {      
          // Validity check
          workflow_envelope workflow(value_of_mu);
          if (workflow.validity_check())
          {
             workflow.run();  
             return 0;
          }
        }
        return 1;
    }