C++ 3 | Static members and friends

3. Static members and friends

1. Constants (C++ uses const like C)

class A{
    public:
    	A():x(100){}
    	const int x;//常数据成员
    	void func() const;//常成员函数
    	const A a;//常对象
}

Example 9, constant member function and constructor parameter passing characteristics

#include <stdio.h>

class A{
	public:
		A(int data = 0,int a = 1):b(data){//初始化表写法
            //一般情况所传参数data赋值给b是在{}里写b=data; 但这里b是常量(const int b)所以只能写成:b(data),为了方便于是就统一写成:b(data)这种初始化表写法。
			this->a = a;//this修饰的a是下面的私有成员int a,使用this是为区分开传参的a
			printf("AAAAAAAAA\n");
		}
		~A(){
			printf("~~~~~~~~~\n");
		}

		void show(void) const
		{
			printf("a = %d\n", a);
			printf("b = %d\n", b);
		}
	private:
		int a;
		const int b;
};

int main()
{
	A x(6);
	x.show();

	A y(7);
	y.show();

	A z;
	z.show();
}

result:

@ubuntu:/mnt/hgfs/ub2/class$ g++ const.cpp 
@ubuntu:/mnt/hgfs/ub2/class$ ./a.out 
AAAAAAAAA
a = 1
b = 6
AAAAAAAAA
a = 1
b = 7
AAAAAAAAA
a = 1
b = 0
~~~~~~~~~
~~~~~~~~~
~~~~~~~~~
@ubuntu:/mnt/hgfs/ub2/class$ 

According to the results, it was found that the value of aalways defaults to 1, this is because the 6 of A x(6); is passed to data, then assigned to b, and finally b is printed out . The parameters of the constructor are passed sequentially , and data comes first, so the parameters are assigned to data.

2. Static members (belonging to classes but not objects)

static int x;
static const int x = 10;
static int A::x = 10;//类外
static void func();
A::func();//类外调用

Example 10. Accessing class members without an object

#include <stdio.h>

class A{
	public:
		void func(void)
		{
			printf("xxxxxxxxx\n");
		}
};

int main()
{
	A a;
	a.func();
}

The above shows the general use of functions: first create an object a, and then use a to access the function func().

but sometimes thinkAccess class member functions without creating an object, so it can be written as:

A::func();

So there are:

#include <stdio.h>

class A{
	public:
		void func(void)
		{
			printf("xxxxxxxxx\n");
		}
};

int main()
{
	A a;
	a.func();
	A::func();
}

The result is an error:

@ubuntu:/mnt/hgfs/ub2/class$ g++ static_1.cpp 
static_1.cpp: In function ‘int main()’:
static_1.cpp:15:10: error: cannot call member function ‘void A::func()’ without object
  A::func();
          ^
@ubuntu:/mnt/hgfs/ub2/class$

The error is becauseOrdinary member functions need to create objects first and then access class member functions based on objects, which can be accessed without an object is a static member function . Generally speaking, ordinary member functions reject singletons (so static is fragrant).

After changing to a static member function as follows:

#include <stdio.h>

class A{
	public:
		static void func(void)
		{
			printf("xxxxxxxxx\n");
		}
};

int main()
{
	A a;
	a.func();
	A::func();
}

result:

@ubuntu:/mnt/hgfs/ub2/class$ g++ static_1.cpp
@ubuntu:/mnt/hgfs/ub2/class$./a.out
xxxxxxxxx
xxxxxxxxx
@ubuntu:/mnt/hgfs/ub2/class$

This is true for member functions, as well as for other data type members, such as static int data:

#include <stdio.h>

class A{
	public:
		static void func(void)
		{
			printf("xxxxxxxxx\n");
		}

		static int data;
};

int A::data = 0;//静态成员需要初始化(在类外)

int main()
{
	A a;
	a.func();
	A::func();
//普通情况
	A x;
	x.data = 6;
	printf("x.data = %d\n", x.data);

//无对象情况
	A::data = 7;
	printf("A::data = %d\n", x.data);
}

result:

@ubuntu:/mnt/hgfs/ub2/class$ g++ static_2.cpp
@ubuntu:/mnt/hgfs/ub2/class$./a.out
xxxxxxxxx
xxxxxxxxx
x.data = 6
A::data = 7
@ubuntu:/mnt/hgfs/ub2/class$

3. Friend (destroying encapsulation)

At the beginning, we bundled and encapsulated them together for security, but later found that in some cases, we still need to make targeted operational changes to the members in the package, so we need friends, so that private ones can be used in specific situations .

friend class B;//友元类
friend void func();//友元函数
friend void B::func();//友元成员函数

Before talking about friends, let’s review a previous case:

Example 11-1. Appending data at the end of an array (review)

arr.h

#ifndef _ARR_
#define _ARR_


class ARR{
public:
	ARR():tail(0){
	}

	void addtail(int data);
	void show(void);
	
private:
	int data[100];
	int tail;
};


#endif

arr.cpp

#include "arr.h"
#include <stdio.h>


void ARR::addtail(int data)
{
	this->data[tail++] = data;
}

void ARR::show(void)
{
	int i = 0;
	for(;i<tail; i++)
		printf("%d, ", data[i]);
	printf("\n");
}

main.cpp

#include "arr.h"

int main()
{

    ARR arr;

    arr.addtail(1);
    arr.addtail(2);
    arr.addtail(5);
    arr.addtail(8);
    arr.addtail(0);
    arr.show();
    
}

result:

@ubuntu:/mnt/hgfs/ub2/ARR4$ ls
arr.cpp  arr.h  main.cpp
@ubuntu:/mnt/hgfs/ub2/ARR4$ g++ *.cpp
@ubuntu:/mnt/hgfs/ub2/ARR4$ ./a.out 
 1, 2, 5, 8, 0, 
@ubuntu:/mnt/hgfs/ub2/ARR4$ 

Now I want to reverse the above data (into 08521). So try the following:

Modify main.c to

#include "arr.h"
void rev(ARR &arr)
{
    int i = 0;
    for(;i<arr.tail/2;i++)
    {
        int tem = arr.data[i];
        arr.data[i] = arr.data[tail-i-1];
        arr.data[arr.tail-i-1] = tem;
    }
}

int main()
{

    ARR arr;

    arr.addtail(1);
    arr.addtail(2);
    arr.addtail(5);
    arr.addtail(8);
    arr.addtail(0);
    arr.show();
    
    rev(arr);
	
    arr.show(); 
}

The result is an error:

@ubuntu:/mnt/hgfs/ub2/ARR4$ ls
arr.cpp  arr.h  main.cpp
@ubuntu:/mnt/hgfs/ub2/ARR4$ g++ *.cpp
In file included from main.cpp:1:0:
arr.h: In function ‘void rev(ARR&)’:
arr.h:15:6: error: ‘int ARR::tail’ is private
  int tail;
      ^
main.cpp:6:16: error: within this context
     for(;i<arr.tail/2;i++)
                ^
In file included from main.cpp:1:0:
arr.h:14:14: error: ‘int ARR::data [100]’ is private
  int data[100];
              ^
main.cpp:8:23: error: within this context
         int tem = arr.data[i];
                       ^
In file included from main.cpp:1:0:
arr.h:14:14: error: ‘int ARR::data [100]’ is private
  int data[100];
              ^
main.cpp:9:13: error: within this context
         arr.data[i] = arr.data[arr.tail-i-1];
             ^
In file included from main.cpp:1:0:
arr.h:14:14: error: ‘int ARR::data [100]’ is private
  int data[100];
              ^
main.cpp:9:27: error: within this context
         arr.data[i] = arr.data[arr.tail-i-1];
                           ^
In file included from main.cpp:1:0:
arr.h:15:6: error: ‘int ARR::tail’ is private
  int tail;
      ^
main.cpp:9:36: error: within this context
         arr.data[i] = arr.data[arr.tail-i-1];
                                    ^
In file included from main.cpp:1:0:
arr.h:14:14: error: ‘int ARR::data [100]’ is private
  int data[100];
              ^
main.cpp:10:13: error: within this context
         arr.data[arr.tail-i-1] = tem;
             ^
In file included from main.cpp:1:0:
arr.h:15:6: error: ‘int ARR::tail’ is private
  int tail;
      ^
main.cpp:10:22: error: within this context
         arr.data[arr.tail-i-1] = tem;
                      ^
@ubuntu:/mnt/hgfs/ub2/ARR4$

The error message contains:

arr.h:15:6: error: ‘int ARR::tail’ is private
arr.h:14:14: error: ‘int ARR::data [100]’ is private

Indicates that the out-of-bounds access to private members was rejected. If you don't want access to be denied in this situation, you need to apply for the function as a friend in the class. (Of course, this function can also be included in the class as a static member function and then called through the class)

Example 11-2, reverse order (become from back to front, not sorting)

arr.h

#ifndef _ARR_
#define _ARR_


class ARR{
public:
	ARR():tail(0){
	}

	void addtail(int data);
	void show(void);
	
    friend void rev(ARR &arr);//把rev函数标记为友元
	
private:
	int data[100];
	int tail;
};


#endif

arr.cpp

#include "arr.h"
#include <stdio.h>


void ARR::addtail(int data)
{
	this->data[tail++] = data;
}

void ARR::show(void)
{
	int i = 0;
	for(;i<tail; i++)
		printf("%d, ", data[i]);
	printf("\n");
}

main.cpp

#include "arr.h"

void rev(ARR &arr)
{
    
    
    int i = 0;
    for(;i<arr.tail/2;i++)
    {
    
    
        int tem = arr.data[i];
        arr.data[i] = arr.data[arr.tail-i-1];
        arr.data[arr.tail-i-1] = tem;
    }
}

int main()
{
    
    

    ARR arr;

    arr.addtail(1);
    arr.addtail(2);
    arr.addtail(5);
    arr.addtail(8);
    arr.addtail(0);
    arr.show();
    
    rev(arr);
	
	arr.show(); 
    
}

result:

@ubuntu:/mnt/hgfs/ub2/ARR5$ ls
arr.cpp  arr.h  main.cpp
@ubuntu:/mnt/hgfs/ub2/ARR5$ g++ *.cpp
@ubuntu:/mnt/hgfs/ub2/ARR5$ ./a.out 
1, 2, 5, 8, 0, 
0, 8, 5, 2, 1, 
@ubuntu:/mnt/hgfs/ub2/ARR5$

After the keyword friend tag, private members can be accessed.

Example 11-3, friend class members (members of class B become friends of class A and then members of class B can access private members of class A)

First, class A creates an object x to access the private member y (A x; xy), and then creates a member function printfA() in class B to print the private member y of object x of class A. Therefore, class B can create an object b, and then use its member function to print the private member y of class A (b.printfA(a);). Under normal circumstances, only one of its members, such as void printfA(A &x), needs to be friended, and other members of class B do not, so it is not appropriate to apply for the entire class B as a friend.

#include <stdio.h>

class A;//这里的存在要引起注意,因为我刻意把案例变得类A中有类B友元处理,类B中成员函数用到类A。
//这种你中有我我中有你就需要这样的重复标识。

class B{
public:
	void printfA(A &x);	
};

class A{
public:
	A()
	{
		y = 100;
	}

//	friend class B;//这句是直接一刀切把整个类友元化
	friend void B::printfA(A &x);//只是针对类B中的一个成员函数友元化
private:
	int y;
};


void B::printfA(A &x)
{
	printf("%d\n", x.y);
}

int main()
{

	A a;
//	printf("%d\n", a.x);

	B b;
	b.printfA(a);
}

result:

@ubuntu:/mnt/hgfs/ub2$ g++ friend.cpp
@ubuntu:/mnt/hgfs/ub2$ ./a.out 
100
@ubuntu:/mnt/hgfs/ub2$

Guess you like

Origin blog.csdn.net/weixin_44035986/article/details/122849434