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:
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 ? :)
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- ...