Nico Schlömer
Nico Schlömer

Reputation: 58721

C++: const-initialize multiple data members from one initializer function

I have a C++ class with two data members, e.g.,

class mytest() {
   public:
     mytest():
        a_(initA()),
        b_(initB())
     {};
     virtual ~mytest() {};

   private:
     double initA() {
        // some complex computation
     }
     double initB() {
        // some other complex computation
     }

   private:
       const double a_;
       const double b_;
}

Unfortunately, though, initA and initB cannot be separated as sketched above. Both a_ and b_ can be initialized by one big complex computation, where the value of b_ depends on an intermediate result in the computation of a_, e.g.,

void mytest::init() const {
   const double a = 1.0 + 1.0;    // some complex computation
   const double b = 2*(a + 1.0);  // another complex computation
   a = 2 * a;  // even more complex, wow
   // Now, a and b contain the data from which a_ and b_ should be initialized.
}

I would like to keep a_ and b_ separate (and const) variables (and not put them in a std::tuple or similar). However, I don't know if it's possible to initialize a_ and b_ separately from a single function.

Any hints?

Upvotes: 6

Views: 380

Answers (3)

Nasser Al-Shawwa
Nasser Al-Shawwa

Reputation: 3653

What I will suggest may seem obvious, but there is absolutely no need to use const for your member variables. If you want your type to be immutable, simply do not provide setter methods, and compute the values of your members in the constructor.

class mytest() {
   public:
     mytest() {
         a_ = 1.0 + 1.0;    // some complex computation
         b_ = 2.0 *(a + 1.0);  // another complex computation
         a_ = 2.0 * a_;  // even more complex, wow      
     };

     // Make your methods const to prevent modification of the members
     void testMethod() const {
         // a_ = 20.0; // Will result in an error!
         std::cout << "sum = " << a_ + b_ << '\n'; // perfectly fine
     }

     virtual ~mytest() {};

   private:
       double a_;
       double b_;
};

This is much simpler, and achieves what you want.

Upvotes: 2

Jarod42
Jarod42

Reputation: 217085

You can add extra intermediate function/struct to initialize your class

with delegating constructor:

struct MytestHelper
{
    double a;
    double b;
};

MytestHelper someComplexComputation(); // feed `a` and `b`

class mytest() {
   public:
     mytest() : mytest(someComplexComputation()) {}
     virtual ~mytest() {};

   private:
     mytest(const MytestHelper& h) : a_(h.a), b_(h.b) {}

   private:
       const double a_;
       const double b_;
};

Upvotes: 5

Simon Goodman
Simon Goodman

Reputation: 1204

You can always cast away the constness, but I would really reconsider your design rather than doing it.

// some pointer
double *ptr;
// give it the value of '_a'
ptr = (double*)( &_a );
// change the value now
*ptr = 5.34;

Also in your code

const double a = 1.0 + 1.0; 

Should be

double a = 1.0 + 1.0; 

No need for it to be const.

Upvotes: -1

Related Questions