Search code examples
c++implementationstatic-methodsfriend

C++ Static Friend Method Example (Need Clarification)


This is a how C++ works question.

I've been looking into the friend modifier and found an example of a static friend method here.

But now I'm having trouble understanding why certain things were done to make it work.

I'm also curious of what practical application this could be used for? When would you want to use static friend? Should this be avoided?

Here's the code with comments added to point out parts I'm confused about.

#include <iostream>

class A; //1. why declare class A here and define it below?

class B
{
public:
    B();
    ~B();

    static void SetAiPrivate(int value); //Makes SetAiPrivate static
    static A *pa; //static instance of class A for class B's static 
                  //methods to use
};

class A
{
friend void B::SetAiPrivate(int); //Gives Class B's SetAiPrivate method access
                                  //to A's private variables

public:
    A(){iPrivate = 0;}
    ~A(){}
    void PrintData(){ std::cout << "iPrivate = "<< iPrivate<<"\n";}

private:
    int iPrivate;
};


A *B::pa;//2. Why is this needed? 
         //   If commented out it causes an external linking error.

B::B()
{
    pa = new A;
}     
B::~B()
{
    delete pa;
}

void B::SetAiPrivate(int value)
{
    pa->iPrivate = value;
}

int main()
{
    B b; //3. Is this necessary? Doesn't C++ automatically initiate static
         //   member variables when a class is referenced

    B::SetAiPrivate(7);
    B::pa->PrintData();
    return 0;
}

Solution

  • Let's look at the code first:

    class A; //1. why declare class A here and define it below?

    That's a forward declaration. B has a member of type A*, so A must be declared beforehand.

    A *B::pa;//2. Why is this needed?

    Static data members are only declared inside the class definition. That's the definition and it's required by the standard to be present in a single translation unit.

    B b; //3. Is this necessary? Doesn't C++ automatically initiate static // member variables when a class is referenced

    Not necessary. Unless of course the static methods in B depend on the run of the constructor. And if they do, it's a bad design.

    Onto the friend question. Usually, having friends breaks encapsulation, be them only members or a whole class. This is no different. It just tells the compiler that A::iPrivate is directly accessible from B::SetAiPrivate.

    This looks wrong to me, as you'd probably want to be able to set A's member directly from A, not from B.