当前位置:   article > 正文

C++中A类内部用B类作为成员变量时的一个坑:invalid use of incomplete type ‘class xxx‘_invalid use of incomplete type 'class build

invalid use of incomplete type 'class build

我们知道,C++中是可以在定义类时嵌套另一个类作为本类的成员的,但是在使用时,有一些细节需要格外注意。

invalid use of incomplete type ‘class xxx’ 问题的出现

首先我们用一段代码来引出这个坑。

我们定义两个类,一个 Person,一个Student。在 Student 中,有一个 Person 类型的成员变量

不过,我们先定义 Student 类,再定义 Person 类。并在 Student 类的定义之前先声明好 Person 类。

class Person; // 前向声明Person类

class Student {
private:
    Person person; // 定义一个Person类的对象作为成员变量
    int grade;
public:
    Student(string name, int age, int grade) : person(name, age), grade(grade) {}
    void print_info() {
        cout << "Name: " << person.get_name() << endl; // 调用Person类的成员函数
        cout << "Age: " << person.get_age() << endl;
        cout << "Grade: " << grade << endl;
    }
};

class Person {
private:
    string name;
    int age;
public:
    Person(string name, int age) : name(name), age(age) {}
    string get_name() { return name; }
    int get_age() { return age; }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

对于上面这段的代码,将会在调用 Student 对象的 print_info() 函数时报错:invalid use of incomplete type ‘class xxx’

问题分析与解决策略

问题分析

  • C++中,如果类中定义另一个类(包括引用和指针,比如Person, Person &, Person *)作为成员变量,那么一定要保证另一个类在本类之前已定义。如果另一个类没定义,而是采用的先写一句声明语句的方式(即前向声明),则在本类成员函数中访问另一个类的成会报错。
  • 因为另一个类只是声明了但未定义,C++编译器又是从上到下编译的,所以编译到这个方法时还不知道另一个类的结构。

解决策略

为了解决上述问题,实际上有两种策略:

  • 可以让另一个类提前定义好,这是最简单和直接的方法,就是将另一个类的定义放在本类之前,这样编译器就可以知道另一个类的大小和结构。
  • 如果上述方案不能解决,那么可以在本类中只声明成员函数,不定义成员函数的函数体。而在类外部,当另一个类已定义完毕后,再去写成员函数的函数体。也就像下面这样:
    class Person; // 前向声明Person类
    
    class Student {
    private:
        Person person; // 定义一个Person类的对象作为成员变量
        int grade;
    public:
        Student(string name, int age, int grade) : person(name, age), grade(grade) {}
        void print_info(); // 只声明不定义
    };
    
    class Person {
    private:
        string name;
        int age;
    public:
        Person(string name, int age) : name(name), age(age) {}
        string get_name() { return name; }
        int get_age() { return age; }
    };
    
    // 在Person类已定义完毕后再定义Student::print_info()函数
    // 编译到这时编译器已经知道Person类的信息了,所以不会报错
    void Student::print_info()
    {
        cout << "Name: " << person.get_name() << endl; // 调用Person类的成员函数
        cout << "Age: " << person.get_age() << endl;
        cout << "Grade: " << grade << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

最后,不得不说,C++的语法相较Java,确实更为繁琐和细致,写的时候一定要小心,从一个个坑中慢慢积累经验~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/121210
推荐阅读
相关标签
  

闽ICP备14008679号