在下面的代码中,构造函数只能在类外部定义,否则编译器会给出错误。
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;
为什么会这样?
答案 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