C++传递类引用时编译报错ParentObject未命名类型如何解决
编译错误原因与修复方案
你遇到的两个错误分别由头文件循环引用、编译配置错误两个问题导致,具体说明如下:
错误1:ChildObject.h第8行报错 'ParentObject' does not name a type
这是典型的头文件循环包含引发的类型识别失败,触发流程如下:
- 两个头文件互相
#include对方,加上#pragma once的防重复包含机制,会导致其中一个类在被引用时还没完成定义 - 以编译
ParentObject.cpp为例:- 编译器首先引入
ParentObject.h,标记该头文件已加载,随即执行里面的#include "ChildObject.h" - 转去处理
ChildObject.h,标记该头文件已加载,随即执行里面的#include "ParentObject.h",发现该头文件已被标记为加载,直接跳过 - 编译器开始定义
ChildObject类,读到void addParent(const ParentObject &po);时,ParentObject类的定义还没执行(需要等回到ParentObject.h后才会开始定义),编译器根本不知道ParentObject是什么类型,就会抛出类型不存在的错误。
- 编译器首先引入
修复方法
头文件中如果只用到类的引用或指针,不需要包含对应类的头文件,用前向声明即可,从根源避免循环包含:
ChildObject.h中删除#include "ParentObject.h",替换为前向声明class ParentObject;,在ChildObject.cpp中再包含ParentObject.hParentObject.h中删除#include "ChildObject.h",头文件内没有用到ChildObject类型,连前向声明都不需要,在ParentObject.cpp中再包含ChildObject.h即可
错误2:ParentObject.cpp第9行报错 cannot convert ‘ParentObject’ to ‘const int&’
这个错误是编译工具和Makefile配置错误叠加导致的:
- 你用编译C语言的
gcc命令编译C代码,gcc默认不会自动链接C标准库,还会套用C语言的隐式声明规则:当编译器识别不到ParentObject类型时,会默认addParent是参数为int类型的C函数,因此抛出类型转换错误 - 同时你的Makefile存在多处语法错误:
- 编译.o目标文件时没加
-c参数,gcc会直接尝试链接生成可执行文件,而非生成目标文件 - 链接生成可执行文件时漏了
-o参数,没有正确指定输出文件名
- 编译.o目标文件时没加
修复方法
- 编译C代码统一使用
g++命令,不需要手动配置C标准库链接 - 修正Makefile的编译、链接参数
修正后的完整代码
ChildObject.h
#pragma once // 前向声明ParentObject类,头文件内仅使用引用不需要完整定义 class ParentObject; class ChildObject { public: ChildObject(); void addParent(const ParentObject &po); };
ParentObject.h
#pragma once class ParentObject { public: ParentObject(); void addChildren(); };
ChildObject.cpp
#include "ChildObject.h" // 实现文件中需要用到ParentObject的完整定义,在此处包含头文件 #include "ParentObject.h" ChildObject::ChildObject() { } void ChildObject::addParent(const ParentObject& po) { }
ParentObject.cpp
#include "ParentObject.h" // 实现文件中需要用到ChildObject的完整定义,在此处包含头文件 #include "ChildObject.h" ParentObject::ParentObject() { } void ParentObject::addChildren() { ChildObject c1; c1.addParent(*this); }
Makefile
test: ParentObject.o ChildObject.o main.o g++ -o test ParentObject.o ChildObject.o main.o ParentObject.o: ParentObject.cpp ParentObject.h g++ -c ParentObject.cpp -o ParentObject.o ChildObject.o: ChildObject.cpp ChildObject.h g++ -c ChildObject.cpp -o ChildObject.o main.o: main.cpp g++ -c main.cpp -o main.o
补充说明
- 头文件包含遵循最小原则:尽量在头文件中用前向声明代替
#include,只有在需要实例化对象、访问类成员、继承类等必须知道类完整结构的场景,才包含对应头文件,可以避免绝大多数循环包含问题 - 单独编译生成
.o目标文件时必须加-c参数,告诉编译器只做编译不做链接 - 链接生成可执行文件时必须加
-o 输出文件名参数,明确指定输出的可执行文件路径
内容的提问来源于stack exchange,提问作者APA
相关产品推荐
相关产品推荐

