构造函数只能在类外定义

时间:2017-04-07 11:23:45

标签: c++ oop

在下面的代码中,构造函数只能在类外部定义,否则编译器会给出错误。

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;
}

它没有编译,但如果我将构造函数的定义移到类外,它会编译:

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

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

错误是:

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;

为什么会这样?

3 个答案:

答案 0 :(得分:4)

为了能够编译此声明

Teacher(Student &s);

编译器只需知道它存在的类Student。前瞻性声明

class Student;

成功地满足了这个要求:它告诉编译器稍后会有类Student的定义。但是,为了能够编译此代码

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

编译器也需要知道Student类的内容。具体而言,它需要知道Student具有成员变量num。在您的程序完全定义Student类之前,这是不可能的。

有两种方法可以解决这个问题:

  • 您已经发现了第一个 - 将构造函数定义移出类或
  • 切换声明的顺序,并转发声明Teacher - 这是可能的,因为Student的代码不依赖于Teacher的定义。

答案 1 :(得分:2)

这与课堂上和课外都没有关系。使用它时,Student类型是否完整(=完全定义)都是关键。

如果您移动Teacher定义的构造函数,但是将其置于Student的定义之上,则会得到完全相同的错误。

由于Teacher构造函数访问Student的成员变量,因此需要查看Student的完整定义。只需切换类定义的顺序。

答案 2 :(得分:1)

嗯,编译器详细解释了它:

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

在第37行,类Student不完整(因为你只是向前宣布它),并禁止访问其成员。

这可以通过将Student类的代码置于Teacher类的代码之上来解决:

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