Classes and objects in C++ 3

1 const modified class member function

The const member functions of the class known as modified const member functions, const member functions actually modify the modified member function implicit this pointer , indicating the member function can not be modified any member of the class .

Insert picture description here

1 Can const objects call non-const member functions?
const Date* this -----> Date* this This is actually the enlargement of the authority, from readable to readable and writable, which of course is not acceptable.
2 Can non-const objects call const member functions?
The principle is similar to 1, Date* this -----> const Date* this, of course it is possible.
3 Can other non-const member functions be called within const member functions?
No
4 Can other const member functions be called from within non-const member functions?
can

2 Take address and const take address operator overload

These two default member functions generally do not need to be redefined, and the compilers generated by default can generally meet daily development.

class Date
{
    
     
public :
 Date* operator&()
 {
    
    
 return this ;
 }
 
 const Date* operator&()const
 {
    
    
 return this ;
 }
private :
 int _year ; // 年
 int _month ; // 月
 int _day ; // 日
};

These two operators generally do not need to be overloaded. You can use the default address-taking overload generated by the compiler. Only in special circumstances, you need to overload, for example, if you want others to get the specified content!

3 Talk about the constructor again

3.1 Constructor body assignment

When creating an object, the compiler gives an appropriate initial value to each member variable in the object by calling the constructor.

class Date
{
    
    
public:
 Date(int year, int month, int day)
 {
    
    
 _year = year;
 _month = month;
 _day = day;
 }
 
private:
 int _year;
 int _month;
 int _day;
};

Although the object has an initial value after the above constructor is called, it cannot be called the initialization of the class object member
. The statement in the constructor body can only be called the initial value, not the initialization. Because initialization can only be initialized once, and the constructor body
can be assigned multiple times.
It can be understood that the constructor body assignment -------->int a; a = 10; And the initialization list to be discussed below is equivalent to int a = 10;

3.2 Initialization list

Initialization list: start with a colon, followed by a comma-separated list of data members, each "member variable" is followed
by an initial value or expression in parentheses . For example, the initialization list of the date class below.

class Date
{
    
    
public:
	Date(int year = 1996,int month = 11,int day = 01)
		:_year(year)
		,_month(month)
		,_day(day)
	{
    
    }
	~Date(){
    
    
		cout << "~Date()" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

3.2.1 Issues that need attention in the initialization list

  • Each member variable can only appear once in the initialization list (initialization can only be initialized once)
  • The class contains the following members, which must be placed in the initialization list for initialization
    1 reference member variables
    2 const member variables
    3 custom type members (the class does not have a default constructor)
class A {
    
    
public:
 A(int a)
 :_a(a)
 {
    
    }
private:
 int _a;
};
class B {
    
    
public:
 B(int a, int ref)
 :_aobj(a)
 ,_ref(ref)
 ,_n(10)
 {
    
    }
private:
 A _aobj; // 没有默认构造函数
 int& _ref; // 引用
 const int _n; // const 
};
  • Try to use the initialization list to initialize, because whether you use the initialization list or not, for custom type member variables, you must
    use the initialization list first .
  • The declaration order of the member variables in the class is the initialization order in the initialization list, which has nothing to do with the order in the initialization list.
    For example, the following program
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();
}

The result is 1 and a random value

3.3 explicit keyword

The constructor can not only construct and initialize the object, but also has the effect of type conversion for the single parameter constructor. Look at the following code

#include <iostream>
#include <windows.h>
using namespace std;

class Date
{
    
    
public:
	Date(int year)
		:_year(year)
	{
    
    
		cout << "Date(int year)" << endl;
	}
	Date(const Date& d)
	{
    
     
		cout << "Date(const Date& d)" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	Date& operator=(const Date& d)
	{
    
    
		cout << "Date& operator=(const Date& d)" << endl;
		if (&d != this)
		{
    
    
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
    
    
	Date d1(2019);
	Date d2 = 2021;
	//d2 = 2030;
	system("pause");
	return 0;
}

The results of the operation are as follows:

Insert picture description here

We found that the constructor was called twice, which involves implicit type conversion =====> First construct an anonymous temporary object of Date (2021), and then use this temporary object to copy and construct d2, and finally the compiler puts these two The two processes are optimized and merged, and the constructor is called directly. We modify the code as follows:

int main()
{
    
    
	Date d1(2019);
	//Date d2 = 2021;
	d1 = 2021;
	system("pause");
	return 0;
}

Insert picture description here

We found that the constructor was called twice, and the assignment operator overloaded once: the anonymous temporary object Date(2021) called the constructor once, and then d1 = Date(2021); the assignment operator overloaded function was called once.
If you don't want the implicit type conversion of a single parameter, you can add the explicit keyword before the constructor .

explicit Date(int year)
		:_year(year)
	{
    
    
		cout << "Date(int year)" << endl;
	}

Insert picture description here

4 static members

4.1 Concept

Class members declared as static are called static members of the class, member variables modified with static are called static member variables;
member functions modified with static are called static member functions. Static member variables must be initialized outside the class

4.2 Features

  • Static members are shared by all class objects and do not belong to a specific instance
  • Static member variables must be defined outside the class , do not add the static keyword when defining
  • Static class members can use static member of a class or object name :: static member access
  • Static member functions have no hidden this pointer and cannot access any non-static members
  • Static members, like ordinary members of a class, also have three access levels: public, protected, and private, and can also have return values
  • Static member functions cannot call non-static member functions (because static member functions have no hidden this pointer)
  • Non-static member functions can call static member functions of the class

5 Default values ​​of member variables in C++11

C++11 supports initialization and assignment of non-static member variables when they are declared, but please note that this is not initialization, here is the
default value for declared member variables .

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:
 // 非静态成员变量,可以在成员声明时给缺省值。
 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;
 }

Non-static member variables can be given default values ​​when the member is declared.
But here is not the initialization, it is the default value. When the constructor does not give a value, it will use the default value here, which
makes up for the constructor automatically generated by the compiler in C++98, and does not deal with the built-in types. The problem.

6 Tomomoto

Friends are divided into: friend functions and friend classes.
Friends provide a way to break through encapsulation and sometimes provide convenience. But friends will increase the coupling and destroy the package, so friends should not be used more
.

6.1 Friend function

class Date
{
    
    
public:
 Date(int year, int month, int day)
 : _year(year)
 , _month(month)
 , _day(day)
 {
    
    }
 
 ostream& operator<<(ostream& _cout)
 {
    
    
 _cout<<d._year<<"-"<<d._month<<"-"<<d._day;
 return _cout;
 }
 prvate:
 int _year;
 int _month;
 int _day
};
int main()
{
    
    
   Date d(2017, 12, 24);
   d<<cout;
   return 0;
}

Question: Now we try to overload operator<<, and then find that we can't overload operator<< as a member function. Because the
output stream object of cout and the implicit this pointer are preempting the position of the first parameter. The this pointer defaults to the first parameter, which is the left operand. But in
actual use, cout needs to be the first formal parameter object before it can be used normally. So we have to overload operator<< as a global function. But in this
case, it will lead to no way to access members outside the class, so here we need friends to solve it. The same is true for operator>>.

The friend function can directly access the private members of the class. It is an ordinary function defined outside the class and does not belong to any class, but it needs to be
declared inside the class , and the friend keyword needs to be added in the declaration.

class Date
{
    
    
friend ostream& operator<<(ostream& _cout, const Date& d);
friend istream& operator>>(istream& _cin, Date& d);
public:
 Date(int year, int month, int day)
 : _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;
 }

note:

  • Friend functions can access the private and protected members of the class, but not the member functions of the class.
  • Friend functions cannot be modified with const, because const modifies the this pointer of the member function, and the friend function is not a member function of the class
  • Friend functions can be declared anywhere in the class definition, and are not restricted by class access qualifiers
  • A function can be a friend function of multiple classes
  • The calling and principle of friend function is the same as that of ordinary function.

6.2 Tomomoto

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

  • The friendship relationship is one-way and not interchangeable. For example, in the Time class and Date class below, declare the Date class as a friend class in the Time class, then you can directly access
    the private member variables of the Time class in the Date class, but you want to access the private members of the Date class in the Time class Variables do not work.
class Date; // 前置声明
class Time
{
    
    
 friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成
员变量
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)
 {
    
    
 // 直接访问时间类私有的成员变量
 _t._hour = hour;
 _t._minute = minute;
 _t.second = second;
 }
 private:
     int _year;
     int _month;
     int _t;
  };
  • Friendship relationship cannot be communicated. If B is a friend of A and C is a friend of B, then it cannot be said that C is a friend of A.

7 Internal category

Concept and characteristics

Concept : If a class is defined inside another class, this inner class is called an inner class. Note that this inner class is an independent
class, it does not belong to the outer class, let alone call the inner class through the object of the outer class. The outer class does not have any superior access rights to the inner class.
Note : The inner class is the friend class of the outer class. Pay attention to the definition of the friend class. The inner class can access
all the members in the outer class through the object parameter of the outer class . But the outer class is not a friend of the inner class.
Features :
1. The inner class can be defined in the public, protected, and private of the outer class.
2. Note that the inner class can directly access the static and enumeration members in the outer class, without the object/class name of the outer class.
3. sizeof (external class) = external class, has nothing to do with internal class.

class A {
    
    
private:
	static int k;
	int h;
public:
	class B
	{
    
    
	public:
		void foo(const A& a)
		{
    
    
			cout << k << endl;//OK
			cout << a.h << endl;//OK
		}
	};
};
int A::k = 1;
int main()
{
    
    
	A::B b;
	b.foo(A());
	system("pause");
	return 0;
}

Insert picture description here

Guess you like

Origin blog.csdn.net/CZHLNN/article/details/114380423