3, Static members and friends
1. Constant (const is used in C + + as in C language)
class A{ public: A():x(100){} const int x;//Constant data member void func() const;//Constant member function const A a;//Constant object }
Example 9. Parameter passing characteristics of constant member functions and constructors
#include <stdio.h> class A{ public: A(int data = 0,int a = 1):b(data){//Initialization table writing method //Generally, when the parameter data is assigned to B, b=data is written in {}; But here B is a constant (const int b), so it can only be written as: b(data). For convenience, it is uniformly written as: b(data). this->a = a;//A modified by this is the following private member int a, and this is used to distinguish a passing parameters 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 is found that the value of a has always been the default value of 1, because A x(6); 6 is passed to data, then assigned to b, and finally printed out b. The constructor passes parameters in sequence, and data comes first, so the parameters are assigned to data.
2. Static member (belonging to class but not object)
static int x; static const int x = 10; static int A::x = 10;//Out of class static void func(); A::func();//Out of class call
Example 10: accessing class members without objects
#include <stdio.h> class A{ public: void func(void) { printf("xxxxxxxxx\n"); } }; int main() { A a; a.func(); }
The above shows the general function usage: first create an object a, and then a accesses the function func().
However, sometimes you want to access class member functions without creating objects, so you can write as follows:
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(); }
Result 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 that ordinary member functions need to create objects first, and then access class member functions according to objects. Static member functions can be accessed without objects. Generally speaking, ordinary member functions reject single dogs (so static is fragrant).
After changing to static member function, it is 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 and for members of other data types, 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;//Static members need to be initialized (outside the class) int main() { A a; a.func(); A::func(); //General situation A x; x.data = 6; printf("x.data = %d\n", x.data); //No object 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 (destroy package)
At first, we bundled and encapsulated them for security, but later we found that in some cases, we still need to make targeted operation changes to the members in the package, so we need friends to make the originally private ones can be used under specific circumstances.
friend class B;//Friend class friend void func();//friend function friend void B::func();//friend member function
Before talking about friends, let's review a previous case:
Example 11-1: adding data at the end of the 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 (become 08521). So try the following:
For main C amend to read
#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(); }
Result 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 includes:
arr.h:15:6: error: 'int ARR::tail' is private
arr.h:14:14: error: 'int ARR::data [100]' is private
Indicates that access to private members was denied when crossing the border. If you don't want access denied in this case, you need to apply the function as a friend in the class. (of course, you can also classify this function into a class as a static member function and call it through the class)
Example 11-2. Reverse order (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);//Mark the rev function as a friend 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 is marked, you can access private members.
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; x.y), 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 print the private member y of class a through its member function (b.printfA(a);). Generally, only one of its members, such as void printfa (a &x), needs friendliness, while other members of class B do not. Therefore, it is inappropriate to apply for the whole class B as a friend.
#include <stdio.h> class A;//Attention should be paid to the existence here, because I deliberately make the case that there are friends of class B in class A, and the member functions of class B use class A. //You have me in you and I have me in you. You need such a duplicate logo. class B{ public: void printfA(A &x); }; class A{ public: A() { y = 100; } // friend class B;// This sentence is a direct one size fits all friendliness of the whole class friend void B::printfA(A &x);//It is only friendly for a member function in class 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$