0

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.

8
  • 3
    Your implementation of B::get_value(A& a) should either be inlined, or moved to a cpp file. Commented May 26, 2023 at 9:10
  • Why are you forward declaring the class A when you immediately provide a definition afterwards? Commented May 26, 2023 at 9:25
  • stackoverflow.com/questions/60860458/… Commented May 26, 2023 at 9:26
  • 1
    In other words, this question has absolutely nothing to do with friend declarations. This question is about the fundamental question of what goes in a header file and what goes in a cpp file. Commented May 26, 2023 at 9:29
  • 1
    @Jason: While the friend declaration does restrict your choice of the inclusion tree, the underlying problem here is that there are cycles in the inclusion graph (it is trying not to be a tree, but the language only allows trees). That problem has nothing to do with friend declarations. Commented May 26, 2023 at 21:11

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.