构造函数只能在类外部定义

Constructor can only be defined outside class

本文关键字:外部 定义 构造函数      更新时间:2023-10-16

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

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;

为什么会这样?

为了能够编译此声明

Teacher(Student &s);

编译器只需要知道类Student它的存在。前向申报

class Student;

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

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

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

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

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

这与类内与类外完全无关。使用类型Student是否完整(= 完全定义(完全取决于

如果您移动 Teacher 定义的构造函数,但将其放在 Student 的定义之上,您将获得完全相同的错误。

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

好吧,编译器详细解释了它:

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