Friend function killed by circle turns on

A class Ais the only instance and container of class instances B.

Thus, it would be nice to make the constructor of the class Bprivate and call it only a friend function declared in the class Band defined in the class A.

Ah file (EDIT: included enum defined in class B)

#ifndef   A_H
#define   A_H

#include "B.h"

using namespace std;

class A
{   public:
    A();
    shared_ptr<B> CreateBInstance( const B::ENUM_STANDARD_COLORS );
    shared_ptr<B> CreateBInstance( const string );  // Custom color

    private:
    unique_ptr<map<int, shared_ptr<B>>> UPTR__BInstancesMap;
}
#endif

Bh file (EDIT: enumeration defined in class B is included)

#ifndef   B_H
#define   B_H

#include "A.h"  // Causes chaos

using namespace std;

class B
{   public:
    enum class ENUM_STANDARD_COLORS : unsigned int
    {   ...     // ~70 standard colors
    };

    private:
    B();

    friend
    shared_ptr<B> A::CreateBInstance( const ENUM_STANDARD_COLORS );

    friend
    shared_ptr<B> A::CreateBInstance( const string );   // Custom color
}
#endif

The class Arequires a full declaration (#include) of the class Bfor shared_ptr<B>.

A class Brequires some class declaration Afor the friend function. A simple forward declaration causes an error:

misuse of the incomplete type 'struc A'

.

(#include) :

error: 'std:: shared_ptr A:: CreateInstance()' 'A'

( !) .
, B :

: "B" ​​
: 1

B A, F G ( ..), # B shared_ptr<B>. < br/" > F G :

: "F" ​​ .
: 1 .
: "G" .
: 1

F G A.

, .

? !

+4
3

A (#include) B shared_ptr<B>.

, A.h . shared_ptr ( unique_ptr) , B return [1] .

A.h

#ifndef   A_H
#define   A_H

class B;  // forward declaration

using namespace std;

class A
{   public:
    A();
    shared_ptr<B> CreateBInstance();

    private:
    unique_ptr<map<int, shared_ptr<B>>> UPTR__BInstancesMap;
};
#endif

[1] "" T, shared_ptr.

+4

, B, .

#include "B.h" 

class B;
+3

A, B ( songyuanyao ), A B.

, , . friend-limited-by-inheritance factory , . , .

A.h

#ifndef   A_H
#define   A_H

#include "B.h"          // The more compelling reason for including B.h is that
                        // classes A thru Z comprise a static library, requiring
                        // only the inclusion of A.h to be used.  B.h through Z.h
                        // must be included directly or indirectly in A.h so that
                        // the caller knows all of the library public functions.

using namespace std     // Makes these examples easier to read.

class A
{   public:
    A();
    shared_ptr<B> CreateBInstance( const B::ENUM_STANDARD_COLORS );
    shared_ptr<B> CreateBInstance( const string );  // Custom color

    private:
//  Please excuse my standards-defying variable names
    unique_ptr<map<int, shared_ptr<B>>> UPTR__BInstancesMap;
}
#endif

A.cpp

#include   "A.h"
#include   "BFactory.h"

...
    shared_ptr<B> A::CreateBInstance( const B::ENUM_STANDARD_COLORS enum__StandardColor )
    {   unsigned int  uint__BInstancesMapIndex = UPTR__BInstancesMap->size();
        shared_ptr<B> sptr__BInstance          = BFactory::CreateBInstance( uint__BInstancesMapIndex, enum__StandardColor );
        UPTR__BInstancesMap->insert( uint__BInstancesMapIndex, sptr__BInstance );
        return sptr__BInstance;
    }

    shared_ptr<B> A::CreateBInstance( const string str___CustomColor )
    {   unsigned int  uint__BInstancesMapIndex = UPTR__BInstancesMap->size();
        shared_ptr<B> sptr__BInstance          = BFactory::CreateBInstance( uint__BInstancesMapIndex, str___CustomColor   );
        UPTR__BInstancesMap->insert( uint__BInstancesMapIndex, sptr__BInstance );
        return sptr__BInstance;
    }
...

B.h

#ifndef   B_H
#define   B_H

using namespace std             // Makes these examples easier to read.

class B
{   public:
    enum class ENUM_STANDARD_COLORS : unsigned int
    {   ...                     // ~70 standard colors
    };

//  virtual                     // BFactory cannot be instantiated; it needs no destructor
    ~B();

    protected:
    static unique_ptr<B> CreateBInstance( const unsigned int, const ENUM_STANDARD_COLORS );
    static unique_ptr<B> CreateBInstance( const unsigned int, const string );   // Custom color

    private:
    B( const unsigned int );    // Eliminates default constructor, therefore BFactory cannot
                                // call B::B(); therefore the compiler does not generate
                                // BFactory::BFactory(); therefore BFactory (and BFactory.o)
                                // is empty; it doesn't even need a cpp file.
}
#endif

B.cpp

#include "B.h"
...
   unique_ptr<B> B::CreateBInstance( const unsigned int uint__BInstancesMapIndex, const ENUM_STANDARD_COLORS enum__StandardColor )
   {   unique_ptr<B> uptr__BInstance = unique_ptr<B>( new B( uint__BInstancesMapIndex ) );
       uptr__BInstance->SetColor( enum__StandardColor );
       return uptr__BInstance;
   }

   unique_ptr<B> B::CreateBInstance( const unsigned int uint__BInstancesMapIndex, const string               str___CustomColor   )
   {   unique_ptr<B> uptr__BInstance = unique_ptr<B>( new B( uint__BInstancesMapIndex ) );
       uptr__BInstance->SetColor( str___CustomColor   );
       return uptr_BInstance;
   }
...

BFactory.h

#ifndef   BFactory_H
#define   BFactory_H

#include  "B.h"

class BFactory : private B          // Make sure anything inherited from B becomes private.
{   friend class A                  // Friend declaration moved from class B.
};

#endif

:
1) A B.
2) B factory , BFactory , BFactory .
3) BFactory - B , ; B factory A .
4) A BFactory B, B.

A factory B, BFactory - .

0

Source: https://habr.com/ru/post/1650871/


All Articles