14.C + + - second order construction mode, friend (detailed explanation)

Posted by gabriel kent on Thu, 02 Apr 2020 21:40:47 +0200

Let's first review the constructors we learned before

  • Class for object initialization
  • The constructor has the same name as the class and does not return a value
  • Constructors are called automatically when they are defined

Since the constructor does not return a value and cannot judge the execution result, there is no guarantee that the initialization object will succeed

For example:

class Test{

private:
   int *p;

public:
   Test(int i)
   {
     p=new int(i);
   }

}

If the new allocation fails when the object is created, a bug will appear. If the code is large, it is difficult to find this problem. This kind of object is called a semi-finished object

 

How to avoid the birth of semi-finished objects?

We will use the second order structure of this chapter

 

Two order structure

The construction process is divided into two steps

-Resource independent initialization

It refers to operations that are not likely to have exceptions, such as initializing common variables such as int and flaot

-Actions that require system resources

It refers to operations that may have abnormal conditions, such as memory application, file access, etc

As shown in the figure below:

 

The steps are as follows:

1. Create a private constructor. Since the constructor does not return a value, it is used for the first stage construction

2. Create a private function with return value for the second stage of construction. If the construction is successful, true will be returned. If the construction fails, false will be returned

3. finally, create a static member function, create an object through new, then call the 1 and 2 step functions, and finally do the judgement processing.

Refer to the following example:

#include <stdio.h>

class TwoPhaseCons
{
private:
    TwoPhaseCons()        // First stage constructor

    {  }

    bool construct()         // Second stage constructor
    {
        return true;
    }

public:
    static TwoPhaseCons* NewObj(); // Object creation function

};


TwoPhaseCons* TwoPhaseCons::NewObj()
{
    TwoPhaseCons* ret = new TwoPhaseCons();

    // If the second stage construction fails, NULL is returned   
    if( !(ret && ret->construct()) )
    {
        delete ret;
        ret = NULL;
    }

    return ret;
}


int main()
{
    TwoPhaseCons* obj = TwoPhaseCons::NewObj();

    printf("obj = %p\n", obj);

    delete obj;

    return 0;
}

  

C++ friends

What is friendship?

Due to the encapsulation of C + + classes, private members of the classes cannot be accessed externally, so friends are born

-A friend of a class can be a function or another class

For example, if the friend of the Test class is a func() function, then the func() function can access any member variables of the Test class (including static, private, shared, etc.)

-The advantage of friend is that it is convenient and quick

-The disadvantage of friend is that it destroys the encapsulation of object-oriented and is gradually abandoned in modern times

 

Friend definition is defined by using the friend keyword in the class, such as:

class Test{
     friend void f_func(const Test& t);        //Declare f func() as a friend of this class
};

void f_func(const Test& t)
{
       ... ...                  //You can access any member variable in the Test class object t
}

 

Example 1

Access the member variable through the friend (function) of the Test class. The code is as follows:

#include "stdio.h"

class Test{

private:
       static int  n;
       int x;
       int y;

public:
       Test(int x,int y)
       {
              this->x = x;
              this->y = y;
       }    

       friend void f_func(const Test& t);         //The friend declaring Test is the f ﹐ func() function

};

int Test::n = 3;   

void f_func(const Test& t)
{
       printf("t.x=%d\n",t.x);   
       printf("t.y=%d\n",t.y);
       printf("t.n=%d\n",t.n);    //Accessing private static member variables
}

int main()
{
       Test t1(1,2);
       f_func(t1);
       return 0;
} 

Run print:

t.x=1
t.x=2
t.x=3

Example 2

The member variable is accessed by a friend of class A (class B), and the code is as follows:

#include "stdio.h"

class A{
       int i;
       int j;

public:
       A()
       {
          i=10;
          j=20;
       }

       friend class B;        //Declare that A's friend is B
};

class B{

public:
       void accessA(const A& t)
       {
          printf("t.i=%d\n",t.i);
          printf("t.j=%d\n",t.j);     
       }

};

int main()
{
    A t1;
    B t2;

    t2.accessA(t1);

    return 0;
} 

Run print:

t.i=10
t.j=20

Topics: C++