I am a beginner learning C++. While studying the topic of friends, I would like to try establishing a friend relationship between the class A in a.h and the class B in b.h, specifically for the get_value() member function. this is my code:
// a.h #ifndef A_H #define A_H #include "b.h" class A; class A { friend void B::get_value(A&); private: double m; int n; public: A(double m = 100, int n = 200) : m(m), n(n) {} }; #endif // b.h #ifndef B_H #define B_H class A; class B { public: void get_value(A&); }; #include "a.h" #include <iostream> void B::get_value(A& a) { std::cout << a.m << a.n << std::endl; return; } #endif // test.cpp #include "a.h" #include "b.h" int main() { A a; B b; b.get_value(a); return 0; } Writing it like this would result in an error, and the error message would be as follows:
E:/project/cpp_project/cpp_study/1. complex/b.h: In member function 'void B::get_value(A&)': E:/project/cpp_project/cpp_study/1. complex/b.h:18:18: error: invalid use of incomplete type 'class A' 18 | std::cout << a.m << a.n << std::endl; I tried alternative approache: define B::get_value(A&) in a.h:
// a.h #ifndef A_H #define A_H #include "b.h" class A; class A { friend void B::get_value(A&); private: double m; int n; public: A(double m = 100, int n = 200) : m(m), n(n) {} }; #include <iostream> void B::get_value(A& a) { std::cout << a.m << a.n << std::endl; // 访问A类的私有成员m和n return; } #endif // b.h #ifndef B_H #define B_H class A; // 前置声明A类 class B { public: void get_value(A&); }; #endif It doesn't work but the error message has changed:
E:/project/cpp_project/cpp_study/1. complex/a.h:21: multiple definition of `B::get_value(A&)'; CMakeFiles/cpp_study.dir/1._complex/test.cpp.obj:E:/project/cpp_project/cpp_study/1. complex/a.h:21: first defined here collect2.exe: error: ld returned 1 exit status ninja: build stopped: subcommand failed. Finally, I reached out to New Bing for help, and I received the answer. It move the definition of B::get_value() into b.cpp:
// a.h #ifndef A_H #define A_H #include "b.h" class A; class A { friend void B::get_value(A&); private: double m; int n; public: A(double m = 100, int n = 200) : m(m), n(n) {} }; #endif // b.h #ifndef B_H #define B_H class A; // 前置声明A类 class B { public: void get_value(A&); }; #endif // b.cpp #include "b.h" // 包含B类的定义 #include "a.h" #include <iostream> void B::get_value(A& a) { std::cout << a.m << a.n << std::endl; // 访问A类的私有成员m和n return; } It works but I don't understand. I hope someone can tell me why my code is error-prone and why bing's code is right.
B::get_value(A& a)should either be inlined, or moved to a cpp file.frienddeclarations. This question is about the fundamental question of what goes in a header file and what goes in a cpp file.