2

I am reading C++ Primer book. It says:

A friend declaration only specifies access. It is not a general declaration of the function. If we want users of the class to be able to call a friend function, then we must also declare the function separately from the friend declaration. To make a friend visible to users of the class, we usually declare each friend (outside the class) in the same header as the class itself.

Watch out for arrow in the code. Which asks my questions at those particular points in reference to above text.

header.h

#ifndef HEADER_H
#define HEADER_H

#include <iostream>
#include <string>

using namespace std;

class Husband{
    friend void change_salary(int changed_salary, Husband &ob);

public:
    Husband() {}
    Husband(unsigned new_salary) : salary{ new_salary } {}

private:
    int salary;

};

//void change_salary(int changed_salary, Husband &ob);  <----Code Compiles without even this declaration

#endif

main.cpp

#include "header.h"

void change_salary(int changed_salary, Husband &ob)
{
    cout << "salary increased by 1000";
    ob.salary = changed_salary;
}


int main()
{
    Husband hs1{ 3000 };

    change_salary(4000, hs1);  // <---- Able to use function without explicit declaration outside of class in header

    return 0; 
}
abhimanyuaryan
  • 3,882
  • 5
  • 41
  • 83
  • Try moving the definition of `change_salary` to `husband.cpp`. You will need to declare the function in `husband.h` then. – Austin Mullins Feb 24 '15 at 19:29
  • @AustinMullins now i kept change_salary code in husband.cpp and included "header.h" .....even then my main.cpp compiles correctly without even separate declaration – abhimanyuaryan Feb 24 '15 at 19:32

3 Answers3

2

You don't need a prototype in the header file if you use the function in the same file it is declared in, after it was declared, which is what you did in main.cpp.

Putting a prototype in the header file helps code in other files, or in the same file but higher up, find the function. It is often a good practice to create a prototype in the header file to make the API clear to human readers. But in the case you have here, it is not strictly required to compile.

amo
  • 4,082
  • 5
  • 28
  • 42
  • so that means i may or may not have it(my choice)? but if i go with proper systematic way then i must have it? – abhimanyuaryan Feb 24 '15 at 19:35
  • 1
    The C compiler will try a few things to find your function before throwing an error, so it may actually compile with a warning about "implicit declaration". – amo Feb 24 '15 at 19:37
  • 1
    You're right that a C compiler would warn about implicit declaration if a function is used without a prior visible declaration/definition, but a C++ compiler would throw an error at that point. (cc @androidplusios.design) – Praetorian Feb 24 '15 at 20:03
1

A friend function declaration is part of your your class design. Without a declaration of the function in your class header (or some included header) your design is incomplete (enforces a user to implement that function or opens the door for some user implementation or causing a one-definition-rule (ODR) violation).

1

You've provided the definition of change_salary before the definition of main() which uses it, so the function is always visible and there are no issues. But let's say you move the definition below that of main() (or to a separate .cpp file).

int main()
{
    Husband hs1{ 3000 };
    change_salary(4000, hs1);
}

void change_salary(int changed_salary, Husband &ob)
{
    cout << "salary increased by 1000";
    ob.salary = changed_salary;
}

The code will continue to compile even in this case because change_salary will be found by argument dependent name lookup (because the second argument is of type Husband&).

Now let's try to explicitly refer to change_salary by forming a pointer to it within main().

void (*p)(int, Husband&) = &change_salary;

This will fail to compile because ADL does not apply in this case, and the definition of change_salary is not visible to main().

However, if you uncomment the declaration of change_salary within the header, the code will compile. This is presumably what the book meant when it said To make a friend visible to users of the class.

Praetorian
  • 106,671
  • 19
  • 240
  • 328