how to correctly initialize instances of a class?

I am not a C++ wizard, so please excuse me if this question is completely stupid.

I am struggling to understand what the correct way to initialize instances of a class for object orient programming is.

If I am not mistaken, there are 2 methods to initialize an instance "instance_name" of CLASS1 by calling the constructor:

(1) CLASS1 instance_name(argument);
(2) CLASS1 instance_name=CLASS1(argument);

As it turns out, I cannot use method (1) when I try to initialize a private instance inside another class. But I can use it in the main() code. I hope the code below will explain what I mean. Can anybody explain why only method (2) will work inside another class? Or is there another fundamental mistake I am making?

(BTW: I used CodeBlocks 13.12 with GNU GCC compiler for this example)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>

using namespace std;

class CLASS1{

  private:
  bool status;

  public:
  // here comes the constructor for CLASS1:
  CLASS1(bool argument){
    status = argument;
    cout << endl;
    cout << "An instance of CLASS1 was created with argument '" << argument << "'" << endl;
  };
  // ... and some simple member function
  bool hasStatus(){
    return status;
  };
};

class CLASS2{

  private:
  bool status;

  CLASS1 Instance1Class1=CLASS1(true); 
  // The above line compiles with a warning "warning:
  // non-static data member initializers only available with -std=c++11 or -
  // std=gnu++11 [enabled by default]".
  // 
  // CLASS1 Instance2Class1(true); will not compile. 
  // There is an error "expected identifier before 'true'"

  public:
  // here comes the constructor for CLASS2:
  CLASS2(bool argument){
    status = argument;
    cout << endl;
    cout << "An instance of CLASS2 was created with argument '" << argument << "'" << endl;
    cout << "This instance of CLASS2 initialised a private instance of CLASS1. The status of this instance is '" << Instance1Class1.hasStatus() << "'"<<endl;
  };
  // ... and some simple member function
  bool hasStatus(){
    return status;
  };
};

int main() {
  CLASS1 Instance1Class1InMain(false);
  CLASS2 Instance1Class2InMain(false);
  CLASS2 Instance2Class2InMain(true);

  cout << endl;
  cout << "The declarations are over and the main program has started." << endl;
  cout << "As you can see from the output above, the declarations of several CLASS1 and CLASS2 objects have already happened. "<< endl << endl;
  cout << "One instance of CLASS1 was initialized in main() with status '" << Instance1Class1InMain.hasStatus() << endl << endl;
  cout << "A first instance of CLASS2 was initialized in main() with status '" << Instance1Class2InMain.hasStatus() << endl;
  cout << "This instance of CLASS2 will have created a private instance of CLASS1 ... I can't read the value from Main(), but I know that CLASS2 objects initilize their CLASS1 objects as '1'." <<endl<< endl;
  cout << "A second instance of CLASS2 was initialized in main() with status '" << Instance2Class2InMain.hasStatus() << endl;
  cout << "This instance of CLASS2 will have created a private instance of CLASS1 ... I can't read the value from Main(), but I know that CLASS2 objects initilize their CLASS1 objects as '1'." <<endl<< endl;
  return 0;
}


And this is the output:

An instance of CLASS1 was created with argument '0'

An instance of CLASS1 was created with argument '1'

An instance of CLASS2 was created with argument '0'
This instance of CLASS2 initialised a private instance of CLASS1. The status of
this instance is '1'

An instance of CLASS1 was created with argument '1'

An instance of CLASS2 was created with argument '1'
This instance of CLASS2 initialised a private instance of CLASS1. The status of
this instance is '1'

The declarations are over and the main program has started.
As you can see from the output above, the declarations of several CLASS1 and CLASS2 objects have already happened.

One instance of CLASS1 was initialized in main() with status '0

A first instance of CLASS2 was initialized in main() with status '0
This instance of CLASS2 will have created a private instance of CLASS1 ... I can't read the value from Main(), but I know that CLASS2 objects initilize their CLASS1 objects as '1'.

A second instance of CLASS2 was initialized in main() with status '1
This instance of CLASS2 will have created a private instance of CLASS1 ... I can't read the value from Main(), but I know that CLASS2 objects initialize their CLASS1 objects as '1'.

Process returned 0 (0x0) execution time : 0.036 s
Press any key to continue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>

using namespace std;

class CLASS1{

  private:
  bool status;

  public:
  // here comes the constructor for CLASS1:
  CLASS1(bool argument){
    status = argument;
    cout << endl;
    cout << "An instance of CLASS1 was created with argument '" << argument << "'" << endl;
  };
  // ... and some simple member function
  bool hasStatus(){
    return status;
  };
};

class CLASS2{

  private:
  bool status;

  CLASS1 Instance1Class1=CLASS1(true);
  // The above line compiles with a warning "warning:
  // non-static data member initializers only available with -std=c++11 or -
  // std=gnu++11 [enabled by default]".
  //
   CLASS1 Instance2Class1; //will not compile.
  // There is an error "expected identifier before 'true'"

  public:
  // here comes the constructor for CLASS2:
  CLASS2(bool argument):Instance2Class1(true)
  {
    status = argument;
    cout << endl;
    cout << "An instance of CLASS2 was created with argument '" << argument << "'" << endl;
    cout << "This instance of CLASS2 initialised a private instance of CLASS1. The status of this instance is '" << Instance1Class1.hasStatus() << "'"<<endl;
  };
  // ... and some simple member function
  bool hasStatus(){
    return status;
  };
};

int main()
{
    std::cout << std::boolalpha;
  CLASS1 Instance1Class1InMain(false);
  CLASS2 Instance1Class2InMain(false);
  CLASS2 Instance2Class2InMain(true);

  cout << endl;
  cout << "The declarations are over and the main program has started." << endl;
  cout << "As you can see from the output above, the declarations of several CLASS1 and CLASS2 objects have already happened. "<< endl << endl;
  cout << "One instance of CLASS1 was initialized in main() with status '" << Instance1Class1InMain.hasStatus() << endl << endl;
  cout << "A first instance of CLASS2 was initialized in main() with status '" << Instance1Class2InMain.hasStatus() << endl;
  cout << "This instance of CLASS2 will have created a private instance of CLASS1 ... I can't read the value from Main(), but I know that CLASS2 objects initilize their CLASS1 objects as '1'." <<endl<< endl;
  cout << "A second instance of CLASS2 was initialized in main() with status '" << Instance2Class2InMain.hasStatus() << endl;
  cout << "This instance of CLASS2 will have created a private instance of CLASS1 ... I can't read the value from Main(), but I know that CLASS2 objects initilize their CLASS1 objects as '1'." <<endl<< endl;
  return 0;
}


1
2
  // CLASS1 Instance2Class1(true); will not compile. 
  // There is an error "expected identifier before 'true'" 

I'm just guessing but I think you compiler is confusing this line for a method
CLASS1 Instance2Class1(bool param = true);// <<---method
Hello Yanson, interesting thought ... that could explain it.

1
2
3
4
5
class CLASS1 {
  VarType Name(Parameters){
  [some code]
  };
}


would declare a method "Name" with parameters "Parameters" that returns a value of type "Vartype"

So if I write

1
2
3
class CLASS2 {
  CLASS1 Name(Parameters);
}


to initialize "Name" as a CLASS1 object, the compiler may not be able distinguish it from the declaration of a method "Name" that should return a CLASS1 value.

In the main() thread, the compiler does not expect method declarations, so

1
2
3
main() {
  CLASS1 Name(Parameters);
}


can only be a variable declaration ... now it starts to make sense.

P.S. what about the code that you included? You seem to have made some changes (lines 33, 38, 53) that I don't understand ...
Last edited on
In the main() thread, the compiler does not expect method declarations, so ... can only be a variable declaration
No. Rules of C++ if something can be threated as function declaration, it will be.
1
2
3
4
5
6
7
8
class foo;

int main()
{
    foo bar();//A function taking no arguments and returning foo by value, not default constructed foo.
    foo bar(foo()); //A function taking a function without parameters and returning foo which returns foo.
    //Not foo instance initializated with default constructed foo.
}
This problem should be fixed with uniform initialization:
1
2
3
4
foo bar; //Works, default approach
foo bar{}; //Calls default constructor explicitely

foo bar(foo{}); //inner foo{} can only be variable, not type, so bar is not a function declaration too 
Hm, ok, that is an even better explanation ... but why do the statements

1
2
3
4
5
6
int main() {
  CLASS1 Instance1Class1InMain(false);
  CLASS2 Instance1Class2InMain(false);
  CLASS2 Instance2Class2InMain(true);
  [...]
}

work as variable declarations? Because the constant as parameter tells the compiler it cannot be function declarations?
Yes, function parameter cannot be threated as type, so it cannot be function declaration.
Perfect. For future reference: "uniform initialization" and "C++'s 'Most Vexing Parse' " are 2 keywords which may help to explain the puzzle.

E.g. "programmers.stackexchange.com/questions/133688/is-c11-uniform-initialization-a-replacement-for-the-old-style-syntax":

This is called C++'s "Most Vexing Parse" because it makes absolutely no sense to a human being. But the rules of C++ sadly require this: if it can possibly be interpreted as a function prototype, then it will be.
Topic archived. No new replies allowed.