如何在Visual Studio(C++11)中处理类的相互依赖/循环依赖
嘿,我来帮你搞定这个类相互依赖的问题!你的代码现在出问题的核心是头文件互相包含,哪怕加了#pragma once也没用——因为预处理的时候会陷入循环,编译器根本没法正确解析两个类的完整定义。
接下来给你一步步改,保证在VS里能正常编译:
第一步:修改头文件,用前向声明替代互相包含
你需要把两个头文件里的#include对方头文件的语句删掉,换成前向声明。前向声明告诉编译器“这个类存在,后面会有完整定义”,这样头文件里的函数声明就能正常用对方类作为参数了。
修改后的A.h:
#pragma once // 删掉#include "B.h",换成前向声明 class B; class A { private: int num; public: A(); void printB(B b); int getA(); ~A(); };
修改后的B.h:
#pragma once // 删掉#include "A.h",换成前向声明 class A; class B { private: char ch; public: B(); void printA(A a); char getB(); ~B(); };
第二步:在.cpp文件中包含对方的头文件
头文件里只有函数声明,而函数实现的时候需要访问对方类的成员(比如b.getB()、a.getA()),这就需要知道对方类的完整定义了。所以你要在各自的.cpp文件里包含对方的头文件。
另外注意:.cpp文件不需要加#pragma once,那是头文件用来防止重复包含的,cpp文件用不上。
修改后的A.cpp:
#include "stdafx.h" #include "A.h" #include "B.h" // 必须包含B的头文件,才能调用B的getB() #include <iostream> A::A() { num = 5; } void A::printB(B b) { std::cout << "b = " << b.getB() << std::endl; } int A::getA() { return num; } A::~A() { }
修改后的B.cpp:
#include "stdafx.h" #include "B.h" #include "A.h" // 必须包含A的头文件,才能调用A的getA() #include <iostream> B::B() { ch = 'g'; } void B::printA(A a) { std::cout << "a = " << a.getA() << std::endl; } char B::getB() { return ch; } B::~B() { }
第三步:修正主文件的包含
主函数里要创建A和B的对象,这需要两个类的完整定义,所以主文件里要同时包含A.h和B.h:
修改后的Interedependency.cpp:
#include "stdafx.h" #include "A.h" #include "B.h" // 必须包含,否则编译器不知道B的完整定义 int main() { A a; B b; a.printB(b); b.printA(a); return 0; }
为什么原来的方法行不通?
- 互相包含头文件:当预处理
A.h时,它会包含B.h,而B.h又要包含A.h,但#pragma once会阻止A.h再次被包含,这时候B.h里的printA(A a)中的A还没有完整定义,编译器会报错“不完整的类型”。 - 前向声明的作用:它只告诉编译器类的存在,不需要知道类的大小或成员,适合在头文件的函数声明中使用;而当需要访问类的成员或创建对象时,就必须包含完整的头文件。
这样改完之后,你在VS里编译运行应该就没问题啦!
内容的提问来源于stack exchange,提问作者theshwetapatil
相关产品推荐
相关产品推荐

