0

I know how to initialize const member in the initializer list, but that requires to know the value to be assigned already when calling the constructor. From what I understand, in java it's possible to initialize a final member in the constructor body, but I haven't seen an equivalent in c++ ( Java's final vs. C++'s const )

But what to do when the initialization is relatively complex? The best I could come up, is to have an initialization function that returns directly an instance. Is there something more concise?

Here is an example (https://ideone.com/TXxIHo)

class Multiplier
{
   const int mFactor1;
   const int mFactor2;
   static void initializationLogic (int & a, int & b, const int c )
   {
       a = c * 5;
       b = a * 2;
    }

  public:
   Multiplier (const int & value1, const int & value2)
     : mFactor1(value1), mFactor2(value2)
     {};
   /*
   //this constructor doesn't initialize the const members
   Multiplier (const int & value)
     {
        initializationLogic(mFactor1,mFactor2, value);
     };
    */
   //this initializes the const members, but it's not a constructor
   static Multiplier getMultiplierInstance (const int & value)
   {
       int f1, f2;
       initializationLogic(f1,f2, value);
       Multiplier obj(f1,f2);
       return obj;
   }
lib
  • 2,918
  • 3
  • 27
  • 53
  • Simple: `const int mFactor1 = 123;`. See [Constructors and member initializer lists](http://en.cppreference.com/w/cpp/language/initializer_list). Drawing parallels between C++ and Java can prove to be counter-productive. – Ron Feb 23 '18 at 19:19
  • @Ron but then mFactor1 would be the same for all the instances, that's not what I want here. I want Factor1 to be assigned at the constructor (with any value, depending on the constructor argument), and not change anymore – lib Feb 23 '18 at 19:23
  • In C++ all objects are initialized before the constructor's body is entered. After that the best you can do is assign and a constant cannot be assigned. The initializer list is your only chance, but you can have a helper function. – user4581301 Feb 23 '18 at 19:24
  • @lib The link I provided covers that part. – Ron Feb 23 '18 at 19:24
  • 2
    `const` members are limiting and rarely necessary. It's generally preferred to just use non-`const` members, even to represent constants, as it preserves assignability and movability for the `class`. The same can be said about reference members. – François Andrieux Feb 23 '18 at 19:25
  • In your particular case... `Multiplier (const int & value): mFactor1{value*5}, mFactor2{mFactor1<<1} { }` – max66 Feb 23 '18 at 19:34
  • @FrançoisAndrieux In this specific case this class was just an helper, used to refactor a long function. It was a bit disappointing that the wall of code was able to express that some parameters are constant, and the more readable class could not... – lib Feb 23 '18 at 19:55

1 Answers1

2

You can delegate object construction to a dedicated constructor accepting an instance of helper class preparing all the necessary parameters:

 private: class
 Init_Helper final
 {
    private: int m_value1;
    private: int m_value2;

    public: explicit Init_Helper(const int c)
    {
        m_value1 = c * 5;
        m_value2 = m_value1 * 2;
        // more init logic goes here...
    }

    public: int const & Get_Value1(void) const
    {
        return m_value1;
    }

    public: int const & Get_Value2(void) const
    {
        return m_value2;
    }
 };

 public: explicit  Multiplier(const int c)
 :  Multiplier{Init_Helper{c}}
 {}

 private: explicit Multiplier(Init_Helper && helper)
 :  mFactor1{helper.Get_Value1()}, mFactor2{helper.Get_Value2()}
 {}
user7860670
  • 35,849
  • 4
  • 58
  • 84
  • Recommendation: Add a usage example to show that in spite of the more-verbose set-up code from the helper class, the actual usage is much, much simpler than Asker's factory approach. That they can just `Multiplier obj(value);` like a civilized human being. – user4581301 Feb 23 '18 at 19:55
  • 1
    Huh, nice "trick". I like that more than I thought I would like something like this. Not a big fan of your Java-like `public:` `private:` repeated everywhere though. – Lightness Races in Orbit Feb 23 '18 at 20:01
  • @user4581301 hey, I came here exactly not to use the factory approach, I think I am civilized :D – lib Feb 23 '18 at 20:12
  • We all try to be civilized. Even me. Then I tack a statement like that onto the end of a perfectly good comment and doubt my commitment to the ideal. – user4581301 Feb 23 '18 at 20:20
  • I was just joking, the meaning of the comment was clear! – lib Feb 23 '18 at 20:25