Still don't get forward declaration in this

  • Thread starter Thread starter yungman
  • Start date Start date
Click For Summary
SUMMARY

This discussion focuses on the concept of forward declaration in C++ and its application in the context of two header files: Auxil.h and Budget3.h. The forward declaration of the class Budget3 in Auxil.h allows the function AuxOffice::addBudget to accept a reference to Budget3 without needing the full definition at that point. The use of the friend keyword in Budget3.h grants AuxOffice access to its private members, emphasizing the importance of understanding the implications of friend functions in class design.

PREREQUISITES
  • Understanding of C++ class structure and header files
  • Familiarity with forward declaration in C++
  • Knowledge of friend functions and their implications in C++
  • Basic understanding of encapsulation and class design principles
NEXT STEPS
  • Research "C++ forward declaration best practices"
  • Learn about "friend functions and classes in C++"
  • Explore "C++ header guards and #pragma once usage"
  • Investigate "design patterns in C++: Memento pattern"
USEFUL FOR

C++ developers, software engineers, and students learning about class design and encapsulation in object-oriented programming.

yungman
Messages
5,741
Reaction score
291
I read about forward declaration on line, it's pretty straight forward. But I don't understand this program from the book:

Line#3 in Auxil.h is Forward Declaration. Line#11 in Budget3.h declare friend void AuxOffice::addBudget(double, Budget3&);

This is Auxil.h
C++:
#ifndef Auxil_H
#define Auxil_H
class Budget3;//Forward declaration of Budget class
class AuxOffice
{ private: double auxBudget;
  public:   
    AuxOffice() { auxBudget = 0; }//Constructor set auxBudget = 0.
    double getDivBudget() const { return auxBudget; }//Something wrong, no return
    void addBudget(double, Budget3&);
        //{auxBudget += fromA; div.corpBudget += fromA;}
};
#endif // !Auxil_H

This is Budget3.h
C++:
#ifndef Budget3_H
#define Budget3_H
#include <iostream>
#include "Auxil.h"
class Budget3
{ private: //corpBudget is static, cannot be declared in Budget3.h, use Budget3.cpp
           static double corpBudget; double divBudget;
  public:  Budget3() { divBudget = 0; }//Constructor starting divBudget = 0
.
.
           friend void AuxOffice::addBudget(double, Budget3&);
};
#endif

1) What I don't quite get is there is no declaration to #include Budget3.h in Auxil.h at the beginning. How does the compiler knows to go to Budget3.h? Is it because Budget3.h declare FRIEND in line 11 that give the permission to the compiler to go out of Auxil.h to search for class Budget3 in budget3.h?

2) Is it true that when Budget3.h declares friend void AuxOffice::addBudget(double, Budget3&); in line 11, the member function b has to pass class Budget3 as reference so there is only one copy of Budget3 in the program?

I am still not comfortable with the FRIEND thing.

Thanks
 
Technology news on Phys.org
jedishrfu said:
I think the budget3 reference is telling the compiler it’s a class to allow its use in defining a function that takes a Budget3 instance as an argument.

the compiler doesn’t need to know anything else about Budget3 to know what to do.

more on friend functions

https://www.geeksforgeeks.org/friend-class-function-cpp/

https://www.tutorialspoint.com/cplusplus/cpp_friend_functions.htm
Thanks

I typed the program of the first link in and play with it. I'll be back.

I think this is exactly what I needed in my other Directory program that I want to have two header files, one for vector of struct management and sorting, one class for file Management to read and write files.

thanks
 
Don’t forget that little header trick in your files it prevents files from being included multiple times should you need construct your headers in a more complicated way.

Code:
#ifndef filename_h
#define filename_h

...

#endif
 
  • Like
Likes yungman
jedishrfu said:
Don’t forget that little header trick in your files it prevents files from being included multiple times should you need construct your headers in a more complicated way.

If one can live with the code not being 100% standardized, #pragma once is a well-supported simple alternative that frees you from having to worry about symbol names.
 
jedishrfu said:
Don’t forget that little header trick in your files it prevents files from being included multiple times should you need construct your headers in a more complicated way.

Code:
#ifndef filename_h
#define filename_h
...
#endif

Thanks, I notice the examples don't have any of these, I have to add them in.

I spent some times on the first link and I actually typed two of them in. I still have a question. Regarding the friend function, it is different if I declare a class as friend or just that particular function as friend. I put this in my notes. You can see Fig.2 to Fig.4 are declaring class A as friend, Fig.5 to Fig.6(forgot to label the last one) only declare function showA() as friend. For function showA() as friend, I cannot have the function body inside any of the header file(see Fig.5). Where as for declaring class A as friend, I can put the body of the function inside class B.in Fig.3.

What is the difference and why? Or it's just is and just remember it? I circled the two lines in question in RED.
Friends.jpg


Thanks
 
Last edited:
Why are you using friend? It is used rarely, and when it is used, it is usually misused. It's a red flag, because it is often used as a band-aid over bad class design, breaking encapsulation rather than fixing the problem.

If it's to allow you to keep your fileClass and vector Class design, you are much better off reworking them as one class as @pbuk suggested.
 
While it may be a RED flag for programmers, its described in his book and so the OP is trying to understand how it is used.
 
  • Like
Likes yungman
I just looked at what's in the book. It does not give a very clear use case: it would be better to create a public method. Or maybe refactor the classes entirely.

I see friend having two primary use cases. One is the Memento design pattern, which allows one to roll an object back to a previous state. The other is an object used only for testing and debugging. There might be some other use cases, but "I want to use a member object directly from another class rather than write an accessor or mutator" is probably not one of them.
 
  • Like
Likes jedishrfu

Similar threads

Replies
6
Views
2K
  • · Replies 13 ·
Replies
13
Views
1K
  • · Replies 36 ·
2
Replies
36
Views
6K
  • · Replies 6 ·
Replies
6
Views
12K
  • · Replies 36 ·
2
Replies
36
Views
3K
  • · Replies 35 ·
2
Replies
35
Views
4K
  • · Replies 17 ·
Replies
17
Views
2K
  • · Replies 57 ·
2
Replies
57
Views
5K
  • · Replies 23 ·
Replies
23
Views
3K
  • · Replies 36 ·
2
Replies
36
Views
3K