错误C2027:使用了未定义类型
当在同一个源文件中定义了两个类,而两个类又相互之间进行引用(如方法中定义形参为另一个类的指针,方法体中通过指针引用成员)时就会报错:C2027:使用了未定义类型
该错误可以通过特别排序的前向声明和单独编译方法解决,下面先介绍一下概念,再给出解决方法
1.先来说说简单的,没有前向引用声明时。
#include <iostream>
#include<string>
using namespace std;
//未加class A时,会报错
class B {
public:
void Bf(A &a) {
cout << "类B中的方法" << endl;
cout << "使用类A的成员" << endl;
}
};
class A {
public:
void Af(B &b) {
cout << "类A中的方法" << endl;
cout << "使用类B的成员" << endl;
}
};
int main() {
A a;
B b;
a.Af(b);
b.Bf(a);
}
加上后:
#include <iostream>
#include<string>
using namespace std;
class A;//加上前向引用后可正常运行
class B {
public:
//A a;不行,会报错:使用了未定义的类型。
//这就说明了如果我们想要用未定义完全的类来实例化一个对象是不可以的,前向引用只能说明有这个东西,定义个形参跟指针啥的还行,但是一旦涉及到具体真实使用就不行了,就会爆错:使用了未定义的类型。
void Bf(A &a) {
cout << "类B中的方法" << endl;
cout << "使用类A的成员" << endl;
}
};
class A {
public:
void Af(B &b) {
cout << "类A中的方法" << endl;
cout << "使用类B的成员" << endl;
}
};
int main() {
A a;
B b;
a.Af(b);
b.Bf(a);
}
2.再来说说复杂的,加上前向引用声明也不行的。
#include <iostream>
#include<string>
using namespace std;
class A;
class B {
public:
A a;//加上了一个用未定义完全的类实例化对象的语句。
void Bf(A &a) {
cout << "类B中的方法" << endl;
cout << "使用类A的成员" << endl;
}
};
class A {
public:
void Af(B &b) {
cout << "类A中的方法" << endl;
cout << "使用类B的成员" << endl;
}
};
int main() {
A a;
B b;
a.Af(b);
b.Bf(a);
}
到这我们肯定会疑问,哎,我不是以及加上了前向引用声明了吗?为什么还会显示使用了未定义类型的”B“呢?
原因:使用向前声明之后,在类定义之前,类是一个不完全类型(incompete type),即仅仅已知向前声明过的类是一个类型,但仍然未实例化,所以在使用向前声明后,类定义前,只能定义指向该类型的指针及引用而不能使用该类成员。
解决方法有俩:1.把需要用到的类提前(编排顺序上下功夫)。 2.单独编译
//提前法,
#include <iostream>
#include<string>
using namespace std;
class B;
class A {
public:
void Af(B& b) {
cout << "类A中的方法" << endl;
cout << "使用类B的成员" << endl;
}
};
class B {
public:
A a;//这里要用A来实例化,所以我们把A定义放到B前面就可以。
void Bf(A &a) {
cout << "类B中的方法" << endl;
cout << "使用类A的成员" << endl;
}
};
int main() {
A a;
B b;
a.Af(b);
b.Bf(a);
}
上述方法有适用范围限制,只有一个类中有另一个类的实际使用才行,两个要是交叉实际使用就不行。
看下面那个程序就不行
#include <iostream>
#include<string>
using namespace std;
class B;
class A {
public:
B b;//这是与上边程序不同的地方,加上了一个B 实例化的
void Af(B& b) {
cout << "类A中的方法" << endl;
cout << "使用类B的成员" << endl;
}
};
class B {
public:
A a;
void Bf(A& a) {
cout << "类B中的方法" << endl;
cout << "使用类A的成员" << endl;
}
};
int main() {
A a;
B b;
a.Af(b);
b.Bf(a);
}
这时候就不行了,就会报错:
这时候就不得不使用单独编译的方法: 原文链接https://blog.csdn.net/qq_43915356/article/details/107577450
通过单独编译和向前声明方法实现两个类之间相互引用成员
向前声明的方法无法使用类的成员,那么只能使编译器知道这是自定义的类类型了
使用预处理指令include,将单独编译的文件引入到预处理命令include的地方
#include 命令是预处理命令的一种,预处理命令可以将别的源代码内容插入到所指定的位置;
C++在同一个项目下的不同文件都位于全局作用域下,在其他文件中也可以引用,如果一个.cpp要用到另一个.cpp定义的函数只需在这个.cpp文件中写上他的函数声明
通过将不同的类分隔成不同的类文件,不同的类将类声明和类定义分隔开,在需要使用其他类时引入目标类的头文件(引入声明)即可使用目标类。
#pragma once
#include <iostream>
#include"SeparateCompilationClass1.h"//编译完成后,预处理器将文件的内容添加到程序中,该头文件就拥有了B类的完整声明
using namespace std;
class B;//使用向前声明,在编译器表示此为一个类类型,使头文件声明通过编译
class A {
public:
void fun(B* b);//由于是声明,所以并不使用类成员,向前声明可以通过编译
};
源文件实现:
#include"SeparateCompilationClass2.h"//A类的头文件,在其中引用了B的头文件,拥有B的完成声明,所以在本文件中可以使用B类成员
void A::fun(B* b) {//通过作用域运算符为A类添加成员定义
cout << "A中的方法" << endl;
cout << "使用B中成员:" << endl;
b->fun();//通过单独编译可以使用B中成员
}
版权声明:本文为hacker_zrq原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。