1

If I have a class that contains more members and some of them are dependent the on others, what is the best way to declare the its members? For example:

class MyClass
{
private:
  MyOb1 Obj1;
  MyOb2 Obj2;
  int i;
  std::string str;

public:
  MyClass(int iIn, const std::string& strIn)
  : i(iIn),      // here
    str(strIn),
    Obj1(i),
    Obj2(i, str) {}
}

There are some problems because of the declaration order. I have chosen that order because it is an optimal order. I need those values in other functions of the MyClass. What is the optimal solution to this problem?

sop
  • 3,445
  • 8
  • 41
  • 84
  • Members are initialised in the order that they are declared: http://stackoverflow.com/questions/2669888/c-initialization-order-for-member-classes, as such your order in the constructor will be ignored – EdChum Jul 30 '14 at 09:49
  • For that situation I would place the integer and string before the MyOb1 and MyOb2 class objects – EdChum Jul 30 '14 at 09:51
  • If Obj1 or Obj2 read the value of i in their constructors, you must put i before them in the class, or you use an uninitialized value. – Neil Kirk Jul 30 '14 at 10:00
  • 1
    avoid ambiguity by doing `Obj1(iIn), Obj2(iIn, strIn)` – M.M Jul 30 '14 at 10:03
  • @MattMcNabb Sure, this is the solution!!! I can do `Obj1(iIn), Obj2(iIn, strIn), i(iIn), str(strIn)`. Why didn't I think f it? – sop Jul 30 '14 at 14:18

1 Answers1

4

As the order of initialisation is dependent on the order they are defined in your class, the member order is ignored: C++: Initialization Order of Class Data Members.

So I would just move the integer and string above MyOb1 and MyOb2, also @Matt McNabb also pointed out that you should use the params passed in your constructor in the initialisation of your MyOb1/2 objects to avoid ambiguity (a sensible suggestion):

class MyClass
{
private:
  int i;
  std::string str;
  MyOb1 Obj1;
  MyOb2 Obj2;


public:
  MyClass(int iIn, const std::string& strIn)
  : i(iIn),      // here
    str(strIn),
    Obj1(iIn),
    Obj2(iIn, strIn) {}
}

To quote from the standard section 12.6.2 (the latest draft has this on page 266):

5 Initialization shall proceed in the following order:

— First, and only for the constructor of the most derived class as described below, virtual base classes shall be initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base class names in the derived class base-specifier-list.

— Then, direct base classes shall be initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).

— Then, nonstatic data members shall be initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).

— Finally, the body of the constructor is executed. [Note: the declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. ]

Community
  • 1
  • 1
EdChum
  • 376,765
  • 198
  • 813
  • 562
  • I know what you are saying, but is this the optimal way to do it? – sop Jul 30 '14 at 10:01
  • Optimal in what sense? This is the *proper* way to do it, there should be no performance cost as your object will be constructed with the right value initially – EdChum Jul 30 '14 at 10:02
  • optimal in the _less memory usage_, _fast_, I do not know... all! :) – sop Jul 30 '14 at 10:03
  • I would say yes, although there may be some fancy c++11/c++14 method that I am not aware of – EdChum Jul 30 '14 at 10:05
  • If you just keep the initial order in declaration of the members it would be optimal – sop Jul 30 '14 at 14:17
  • @sop it is recommended to initialise the members in the order they are declared for clarity, but it doesn't affect the order as per the standard – EdChum Jul 30 '14 at 14:20
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/58362/discussion-between-sop-and-edchum). – sop Jul 30 '14 at 14:58