2

Just read about friend functions and I'm trying to access private variable "number" in class A with friend function "Print" from class B. I'm working with Visual Studio. Compilation of my code gives me plenty of various errors like:

C2011: 'A' : 'class' type redefinition
C2653: 'B' : is not a class or namespace name

Please be patient with me me and show a proper way of achieving my goal.

Here are my files A.h:

class A
{
public:
    A(int a);
    friend void B::Print(A &obj);
private:
    int number;
};

A.cpp:

#include "A.h"

A::A(int a)
{
    number=a;
}

B.h:

#include <iostream>
using namespace std;
#include "A.h"
class B
{
public:
    B(void);
    void Print(A &obj);
};

B.cpp:

#include "B.h"

B::B(void){}

void B::Print(A &obj)
{
    cout<<obj.number<<endl;
}

main.cpp:

#include <iostream>
#include <conio.h>
#include "B.h"
#include "A.h"

void main()
{
    A a_object(10);
    B b_object;
    b_object.Print(A &obj);
    _getch();
}
jparthj
  • 1,606
  • 3
  • 20
  • 44
QED
  • 77
  • 1
  • 8
  • 2
    tip: class `B` doesn't actually need to know the details of `A`, all it needs to know is that class `A` _exists_. – Mooing Duck Dec 14 '12 at 19:09
  • remove `friend void B::Print(A &obj);`, add `friend class B;` or follow Mooning Ducks tip. – andre Dec 14 '12 at 19:11
  • In B.h remove `#include "A.h"` and add `class A;` then add `#include "A.h"` in B.cpp – Ben Dec 14 '12 at 19:14

2 Answers2

3

... Second you might need a forward declaration of class B in the A.h header file to refer B as a friend:

#ifndef _A_H_
#define _A_H_
class B;

class A
{
     friend class B;
};
#endif

UPDATE
I'm currently not so sure if it's possible to declare member functions as friends, I'll have a look.

It's not possible to create member function friend declarations, you can either declare global functions or whole classes as friend, see also: C++ ref, Friendship and inheritance.

In general it's not a good design idea to use friend at all, because it strongly couples the classes together. The better solution will be to couple interfaces (which don't need to be publicly visible anyways).
In rare cases it might be a good design decision but that almost always applies to internal details.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • 1
    Using `friend` isn't always bad. See http://www.parashift.com/c++-faq/friends-and-encap.html – Fred Larson Dec 14 '12 at 19:39
  • @FredLarson Yes, I mentioned that Fred. Anyway it's already deprecated in UML and you can usually replace the need for `friend` declarations using either abstract (pure virtual) or static (template) interfaces. This might also give you the fine grained control over what exactly can be accessed by a 'friend' class or method. – πάντα ῥεῖ Dec 14 '12 at 19:44
1

First you need to put

#ifndef A_H
#define A_H
.... your A-class definition
#endif

in your A.h and analogous in B.h, so that multiple includes of the same file is prevented (that is your duplicate definition error)...

pbhd
  • 4,384
  • 1
  • 20
  • 26
  • 1
    Or you can put "#pragma once" at the begining of your .h files. – PRouleau Dec 14 '12 at 19:22
  • 1
    No, please: remove the double underscores. Names that contain two underscores and names that begin with an underscore followed by a capital letter are reserved to the implementation. Don't use them. – Pete Becker Dec 14 '12 at 19:23
  • 1
    @PRouleau Hmm. If you are in the Visual C++-World. Not sure wether gcc understands that? – pbhd Dec 14 '12 at 19:24
  • Well, the OP didn't mention the code should be portable and it does use Visual Studio. As for GCC, it does understand it. See http://stackoverflow.com/questions/787533/is-pragma-once-a-safe-include-guard I prefer to use it because it is one line and have no chance to conflic with another header file. – PRouleau Dec 14 '12 at 19:31
  • I would add that the OP is starting with C++. Where should he learn that the #define with underscores are reserved? I searched "c++ #define" and it is not specified in its description. Of course, any good book or tutorial would mention the importance to use include guards, but not always about the reserved rules. – PRouleau Dec 14 '12 at 19:46