Korchkidu
Korchkidu

Reputation: 4946

Delegating Constructors with In-Class Member Initialization

I would like to do something like the following:

class DelegatingCTorPlusInClass
{
public:
  DelegatingCTorPlusInClass()
    :
    DelegatingCTorPlusInClass(m_a, m_b) // m_a and m_b are "random"
  {
  };

  DelegatingCTorPlusInClass(int a)
    :
    DelegatingCTorPlusInClass(a, m_b) // m_b is "random"
  {
  };

  DelegatingCTorPlusInClass(const std::string &b)
    :
    DelegatingCTorPlusInClass(m_a, b) // m_a is "random"
  {
  };

  DelegatingCTorPlusInClass(int a, const std::string &b)
    :
    m_a(a),
    m_b(b)
  {
    // DO THINGS
  };

private:
  int m_a = 42;
  std::string m_b = "42";
};

However, members passed from one constructor to the other are not yet initialized so are basically "random". How could I achieve something similar then?

Upvotes: 1

Views: 693

Answers (3)

Casey
Casey

Reputation: 42554

You are not required to use non-static data member initializers and delegating constructors simply because they exist. What's wrong with:

class DelegatingCTorPlusInClass
{
public:
  DelegatingCTorPlusInClass(int a = 42, std::string b = "42")
  : m_a(a), m_b(std::move(b))
  {
    // DO THINGS
  }

private:
  int m_a;
  std::string m_b;
};

Upvotes: 0

Anton Savin
Anton Savin

Reputation: 41301

[class.base.init]/9:

If a given non-static data member has both a brace-or-equal-initializer and a mem-initializer, the initialization specified by the mem-initializer is performed, and the non-static data member’s brace-or-equal-initializer is ignored.

Which justifies that in the main constructor you assign members with garbage:

DelegatingCTorPlusInClass(int a, const std::string &b)
    :
    m_a(a), // this is mem-initializer for m_a, so m_a = 42 is ignored and you are getting garbage
    m_b(b) // the same for m_b
{
};

To avoid duplication of default values you can use constants for them, so you'll have something like:

DelegatingCTorPlusInClass() : DelegatingCTorPlusInClass(m_a_default, m_b_default)
{
};

Upvotes: 1

Jay Miller
Jay Miller

Reputation: 2234

You want to build up defaults from the constructors with fewer arguments, rather than relying on inline initialization.

class DelegatingCTorPlusInClass
{
public:
  DelegatingCTorPlusInClass()
    :
    DelegatingCTorPlusInClass(42, "42") // default values
  {
  };

  DelegatingCTorPlusInClass(int a)
    :
    DelegatingCTorPlusInClass(a, "42") 
  {
  };

  DelegatingCTorPlusInClass(const std::string &b)
    :
    DelegatingCTorPlusInClass(42, b) 
  {
  };

  DelegatingCTorPlusInClass(int a, const std::string &b)
    :
    m_a(a),
    m_b(b)
  {
    // DO THINGS
  };

private:
  int m_a;
  std::string m_b;
};

A constructor should define what the value requirements are for that usage. Inline initialization only makes sense when it is true for all constructors.

Upvotes: 0

Related Questions