C++ Classes and Objects

Re-talk about constructors Initia...
Initialization List
explicit keyword
friend function
friend class

Re-talk about constructors

Initialization List

class A { public: A(int a = 0) { _a = a; } A& operator=(const A& aa) { if (this != &aa) { _a = aa._a; } return *this; } private: int _a; }; class B { public: B(int a, int b) { //A a a(a); // Private cannot be accessed. First construct a class A object //_ aa = aa; // assignment _aa = A(a);//Anonymous object, life cycle is just this statement. Because the constructed class A object is only assigned to _ aa _b = b; } private: int _b = 1;//Built-in type A _aa; //Custom Type }; int main() { B b(10, 20); return 0; }

In the above code, we initialize within the constructor body, which is inefficient. When constructor B is called, the constructor of A is called once by default, modifying _ The value of aa, that is _ A a=A(a); In, the A constructor is called once more, and the assignment overload function is called once more, so initialize _ AA is more expensive. We can use the initialization list.

Initialization list: Start with a colon, followed by a comma-separated list of data members, with each "member variable" followed by an initial value or expression in parentheses.

class B { public: B(int a, int b) :_aa(a) , _b(b) {} private: int _b = 1; A _aa; };

Regardless of whether an initialization list is used or not, for custom type member variables, the initialization list must be used first. For the above code, using initialization list instead will only call A's constructor once, which improves efficiency.

[Attention]

  1. Each member variable can only appear once in the initialization list (initialization can only occur once)
  2. The class contains the following members and must be initialized in the initialization list location:
    Reference member variable, const member variable
    Custom type member (this class does not have a default constructor)
    Because const and members of reference types must be initialized at definition time
class B { public: B(int c,int& ref,int a) :_c(c) ,_ref(ref) ,_aa(a) { _ref = 100; } private: const int _c; int& _ref; A _aa; }; int main() { int ref = 10; B b(1, ref, 1000); cout << ref << endl; return 0; }

The value of the output ref is 100.
Initialization lists and in-body initializations can be mixed and used in conjunction with each other. Some initializations cannot be accomplished with an initialization list, but must also be initialized within the function body, such as a leading bidirectional loop chain table.

  1. The order in which member variables are declared in a class is the order in which they are initialized in the initialization list, irrespective of their order in the initialization list.
class A { public: A(int a) :_a1(a) ,_a2(_a1) {} void Print() { cout << _a1 << " " << _a2 << endl; } private: int _a2; int _a1; }; int main() { A aa(1); aa.Print(); return 0; }

The final output is: 1 random value
The declaration order and the initialization list order are best aligned to avoid such problems.

explicit keyword

class A { public: A(int a) :_a(a) {} private: int _a; }; int main() { A aa = 2; return 0; }


This is essentially an implicit type conversion, which opens up a temporary space. Here, a temporary object is constructed with 2 first, then AA is copied with this temporary object to construct aa, and the final vs compilation is optimized (the premise of optimization is a continuous statement, if A aa; aa=2; two statements will not be optimized), optimization uses 2 as a parameter to construct AA directly without temporary space. A aa1(1); A aa2=2; They all call the constructor directly, but the procedure is different for the compiler.

static member

Class members declared as static are called static members of the class, and member variables modified with static are called static member variables. A member function modified with static is called a static member function. Static member variables must be initialized outside the class.
Role of static: In C language, 1. can modify global variables and global functions, change link properties so that they are only visible in the current file. 2. Modify local variables to change life cycle. These features are still useful in C++, which is compatible with C+. CPP: modifies member variables and member functions, member variables belong to the entire class, all objects are shared, static member functions do not have this pointer.

Example: Implement a class and how many class objects are created in the calculator.

class A { public: A() { ++_scount; } A(const A& t) { ++_scount; } static int GetACount() { return _scount; } private: int _a; static int _scount; }; int A::_scount = 0; int main() { A a1, a2; A a3(a1); cout << A::GetACount() << endl; return 0; }

Output result is 3
Compared with global variables, he is restricted by class domains and access qualifiers and cannot be easily modified to better reflect encapsulation.

cout<<sizeof(A)<<endl;

sizeof(A) is the size of the object defined by A. In the above example, sizeof(A) is 4, which is the size of int. Statics belong to the entire class and to each defined object share, not counting in object size.

Access to non-static member functions requires a this pointer, whereas static member functions do not have a this pointer, so static member functions cannot access non-static member functions, while non-static member functions can access static member functions (static functions can be accessed with class domains).

C++11 supports default values for nonstatic member variables when declared. Static members cannot. Static members are no longer initialized by constructors, but initialization is defined globally outside the class.

class B { public: B(int b = 0) :_b(b) {} int _b; }; class A { public: void Print() { cout << a << endl; cout << b._b<< endl; cout << p << endl; } private: // A non-static member variable that can be given a default value when a member is declared. int a = 10; B b = 20; int* p = (int*)malloc(4); static int n; }; int A::n = 10; int main() { A a; a.Print(); return 0; }
Friends

Friends are divided into: Friend function and Friend class. Friends provide a way to break through encapsulation and sometimes provide convenience. Friends, however, increase the coupling and destroy the encapsulation, so they should not be used more often.

friend function

Problem: Now we try to overload operator<<, and find that we can't overload operator< as a member function. Because the output stream object of the cout and the implicit this pointer are preempting the position of the first parameter. The this pointer defaults to the first parameter, the left operand. However, in practice, cout needs to be the first parameter object in order to work properly. So we're going to overload operator < as a global function. However, if this happens, it will make it impossible to access members outside of the class, so friends are needed to solve this problem. Operator > the same.
friend functions have direct access to private members of a class. They are common functions defined outside the class and do not belong to any class. They need to be declared inside the class, with the friendly keyword added.

class Date { friend ostream& operator<<(ostream& _cout, const Date& d); friend istream& operator>>(istream& _cin, Date& d); public: Date(int year=0, int month=0, int day=1) : _year(year) , _month(month) , _day(day) {} private: int _year; int _month; int _day; }; ostream& operator<<(ostream& _cout, const Date& d) { _cout << d._year << "-" << d._month << "-" << d._day; return _cout; } istream& operator>>(istream& _cin, Date& d) { _cin >> d._year; _cin >> d._month; _cin >> d._day; return _cin; } int main() { Date d; cin >> d; cout << d << endl; return 0; }

Explain:

  • Friend functions can access the private and protect members of a class, but are not member functions of the class. Friend functions cannot be const-modified. Friend functions can be declared anywhere in a class definition and are not restricted by class access qualifiers. A function can be a friend function of multiple classes. Friend functions are called in the same way as normal functions.

friend class

All member functions of a friend class can be friend functions of another class, and non-public members of another class can be accessed.

1. Friend relationship is one-way and not exchangeable.

  • For example, if you declare the Date class as its friend class in the Time class, you can access the private member variables of the Time class directly in the Date class, but you cannot access the private member variables of the Date class in the Time class.

2. Friendship cannot be transferred

  • If C is the friend of B and B is the friend of A, C cannot be said to be the friend of A.
class Date; // forward declaration class Time { friend class Date; // Declaring a date class as a friend of the time class directly accesses the private member variables in the Time class in the date class public: Time(int hour, int minute, int second) : _hour(hour) , _minute(minute) , _second(second) {} private: int _hour; int _minute; int _second; }; class Date { public: Date(int year = 1900, int month = 1, int day = 1) : _year(year) , _month(month) , _day(day) {} void SetTimeOfDate(int hour, int minute, int second) { // Direct access to time class private member variables _t._hour = hour; _t._minute = minute; _t._second = second; } private: int _year; int _month; int _day; Time _t; };

8 November 2021, 11:52 | Views: 4085

Add new comment

For adding a comment, please log in
or create account

0 comments