user7832248
user7832248

Reputation:

Constructor can only be defined outside class

In the following code, the constructor can only be defined outside the class, or compiler will give errors.

class Student;
class Teacher 
{
private:
    int num;
    string name;
    string sex;
    string title;
public:
    Teacher(Student &s) {
        num=s.num ;
        name=s.name ;
        sex=s.sex ;
    }
    void display();
};

class Student
{
public:
    int num;
    string name;  
    string sex;
    float grade;
    friend Teacher;
    void set_student();
};

void Teacher::display()
{
    cout<<num<<" "<<name<<" "<<sex<<endl;
} 


void Student::set_student() 
{ 
    cin>>num>>name>>sex>>grade;
} 


int main()
{
    Student s1;
    s1.set_student() ;
    Teacher t1(s1);  
    t1.display() ;
    return 0;
}

It didn't compile, but if I move the definition of the constructor outside the class, it compiles:

class Teacher
{
public:
Teacher(Student &s);
...
};

Teacher::Teacher(Student &s)
{
    num=s.num ;
    name=s.name ;
    sex=s.sex ;
}   

The error is:

floyd.cpp: In constructor 'Teacher::Teacher(Student&)':
floyd.cpp:37:8: error: invalid use of incomplete type 'class Student'
   num=s.num ;
        ^
floyd.cpp:27:7: error: forward declaration of 'class Student'
 class Student;
       ^
floyd.cpp:38:9: error: invalid use of incomplete type 'class Student'
   name=s.name ;
         ^
floyd.cpp:27:7: error: forward declaration of 'class Student'
 class Student;
       ^
floyd.cpp:39:8: error: invalid use of incomplete type 'class Student'
   sex=s.sex ;
        ^
floyd.cpp:27:7: error: forward declaration of 'class Student'
 class Student;

Why does this happen?

Upvotes: 2

Views: 96

Answers (3)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726499

In order to be able to compile this declaration

Teacher(Student &s);

the compiler needs to know about class Student only that it exists. Forward declaration

class Student;

successfully fulfills this requirement: it tells the compiler that there is going to be a definition of class Student at some later point. However, in order to be able to compile this code

Teacher(Student &s) {
    num=s.num ;
    ...
}

the compiler needs to know the content of the Student class as well. Specifically, it needs to know that Student has member variable num. This is not possible until the point of your program where Student class is fully defined.

There are two ways of addressing this issue:

  • You already discovered the first one - move constructor definition out of the class, or
  • Switch the order of declarations, and forward-declare Teacher - this is possible because Student's code does not depend on Teacher's definition.

Upvotes: 4

This is not related to in-class vs. out-of-class at all. It's all the matter of whether the type Student is complete (= fully defined) when you use it.

You'll get the exact same error if you move the constructor of the definition of Teacher, but place it above the definition of Student.

Since the Teacher constructor accesses member variables of Student, it needs to see the full definition of Student. Just switch the order of the class definitions.

Upvotes: 2

alexeykuzmin0
alexeykuzmin0

Reputation: 6440

Well, the compiler explains it in detail:

floyd.cpp: In constructor 'Teacher::Teacher(Student&)':
floyd.cpp:37:8: error: invalid use of incomplete type 'class Student'
   num=s.num ;

On the line 37 the class Student is incomplete (since by that line you only forwardly declared it), and accessing its members is prohibited.

This may be fixed by placing the code of Student class above the code of Teacher class:

class Teacher; // Forward declaration, for the 'friend' line
class Student {..}; // All the code you now have in the Student class
class Teacher {..}; // All the code of Teacher class

Upvotes: 1

Related Questions