3

I've written this code:

#include<iostream>

using namespace std;

class Student {
   public:
      string name;
      int age;
      Student() {
         cout<<"Default constructor"<<endl;
      }
      Student(string name, int age) {
         this->name=name;
         this->age=age;
         cout<<"Parameterized constructor"<<endl;
      }
};

int main() {
   system("clear");
   Student s1={"abc", 20};                                                                                                                                                                                                                                                 return 0;                                                                                                                        }

Result:

Parameterized constructor

Conclusion: Defining object s1 like this Student s1={"abc", 20} calls parameterized constructor of class

Testing out conclusion:

#include<iostream>

using namespace std;

class Student {
   public:
      string name;
      int age;
};

int main() {
   system("clear");
   Student s1={"abc", 20};

   return 0;
}

But compiling the code above doesn't give any errors.

Questions:

  1. Why there is no errors even if we don't define any parameterized constructor inside class ?
  2. When we define class data members as private, we get some error:
5.cpp:12:12: error: no matching constructor for initialization of 'Student'
   Student s1={"abc", 20};
           ^  ~~~~~~~~~~~
5.cpp:5:7: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
class Student {
      ^
5.cpp:5:7: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
5.cpp:5:7: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided
1 error generated.

Why we are getting this error now and not when data members were public ? :)

1
  • To answer #1 :Aggregate initialization takes place as your type is an aggregate type. Commented Feb 7, 2022 at 4:43

1 Answer 1

2

For the 1st case, Student has user-declared constructors, Student s1={"abc", 20}; performs list-initialization, as the effect, the appropriate constructor Student::Student(string, int) is selected to construct s1.

If the previous stage does not produce a match, all constructors of T participate in overload resolution against the set of arguments that consists of the elements of the braced-init-list, ...

For the 2nd case, Student has no user-declared constructors, it's an aggregate and Student s1={"abc", 20}; performs aggregate-initialization, as the effect the data member name and age are initialized from "abc" and 20 directly.

An aggregate is one of the following types:

  • ...
  • ... class type (typically, struct or union), that has
  • ...
    • no user-declared or inherited constructors
  • ...

Each direct public base, (since C++17) array element, or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.

If you make data members private, Student is not aggregate again. Student s1={"abc", 20}; still performs list-initialization and causes the error since no appropriate constructor exists.

An aggregate is one of the following types:

  • ...
  • ... class type (typically, struct or union), that has
    • no private or protected direct (since C++17)non-static data members
  • ...
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.