Kei Minagawa
Kei Minagawa

Reputation: 4521

c++ constructor and initializer behavior. What's the difference between these 5 codes?

I'm new to c++ programming language. I wrote several patterns of code to understand c++ constructor and initializer. But I couldn't find out why one build fail and another doesn't. From my view, there seems no such difference that one fail and another doesn't. The code is the following 5 codes. What's the difference between code example 1-2, 2-3, 3-4, 4-5. Why one fail but another doesn't?

Additional Info: I'm building these code with Xcode 8.2.


The Code

Example 1:

class A{
public:
  A(int xxx) { }
};

int main(){
  A a; // Fail here. I see this is because there is no default constructor in definition of class A.
}

Example 2:

class A{
public:
  A(int xxx) { }
};

class B{
public:
  A a; // No fail. Why? I supposed it will fail like Example 1.
};

int main(){

}

Example 3:

class A{
public:
  A(int xxx) { }
};

class B{
public:
  A a;           // No fail here.
  B(int xxx) { } // But fail here. Why? I just added constructor to Example 2.
};

int main(){

}

Example 4:

class A{
public:
  A(int xxx) { }
};

class B{
public:
  A a;
  B(int xxx) : a(123) { } // No fail. Why Just adding ":a(123)" works.
};

int main(){

}

Example 5:

class A{
public:
  A(int xxx) { }
};

class B{
public:
  A a;
  B(int xxx){ a = 123; } // Fail again. Why? I think ":a(123)" and "a=123" is same meaning.
};

int main(){

}

Upvotes: 0

Views: 104

Answers (3)

Rama
Rama

Reputation: 3305

  • 1 vs 2: Example 2 don't fail because you never instantiate B o A in your main
  • 2 vs 3: Example 3 fail because in you constructor of B you don't call to A::A() and A has no default constructor
  • 3 vs 4: Example 4 don't fail because you call to A::A() in your B constructor.
  • 4 vs 5: Example 5 fail because (again)you don't call to A::A() and A has no default constructor. But 123 can be asigned to A (because the implicitly-declared copy assignment operator is declared, and you have a constructor to build an A from an int)

Upvotes: 0

Agentlien
Agentlien

Reputation: 5136

You seem to be getting the hang of most of this, so let me go through them all and clarify.

Example 1: You're trying to create an instance of A without supplying the constructor arguments it needs.

Example 2: The class B can't be instantiated since it needs to create an instance of A and you haven't specified which arguments to send to its constructor. You would get a compiler error here if you were to create an instance of B somewhere. For example by putting B b; in main().

Example 3: The constructor B::B(int) fails to compile because you haven't specified valid arguments to the constructor of B::a (its instance of A). You're getting the error here, since it's during this constructor you would have to specify the arguments to a``.

Example 4: Here you are specifying, in the initialization list of B::B which arguments it should pass to B::a. This is what you need to do in order for it to compile.

Example 5: Here you're trying to assign a the value of 123. This is done in the body of the constructor B::B, which is called after all members of B have been initialized. It's not specifying the arguments to the constructor of a. It's just trying to assign a new value to it after it has already been constructed. Since you're not specifying a value which should be sent to the constructor of a, you get the same error as in Example 3.

Upvotes: 2

NathanOliver
NathanOliver

Reputation: 181068

There is no error for example 2 since you never try to construct a B. If you add to main B b; then you will get an error like

error: use of deleted function 'B::B()'

The reason you do not get an error before you try to instantiate a B is because A a; is just a member declaration. It is not until the constructor is called and you try to instantiate a that you find out it is not default constructable.

Example 3 is basically the same thing. Now that you are defining a constructor the compiler will automatically add the default initialization of a to it since you did not provide one in the member initializer list. When it does that it sees A is not default constructable so it issues the error.

Example 4 does not fail because you specify how to construct a. Since you did that the compiler will not try to default construct it and instead it constructs a with the value you provided.

Example 5 fails again because of the same reason in example 3. It tries to add a default initialization to the member initialization list but can't since it does not exists, which give you the error.

Upvotes: 4

Related Questions