[C++] Classes and Objects (Part 2)

Constructor again

Constructor body assignment

When creating an object, the compiler calls the constructor to give each member variable in the object an appropriate initial value.

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

Although there is already an initial value in the object after the above constructor is called, it cannot be called the initialization of a class object member, and the statements in the constructor body can only be called as initial value, not initialization. Because initialization can only be initialized once, and the constructor body can be assigned multiple times.

initialization list

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

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

【Notice】

  1. Each member variable can only appear once in the initialization list (initialization can only be initialized once)

  2. The class contains the following members, which must be initialized in the initialization list:

    引用成员变量
    const成员变量
    自定义类型成员(该类没有默认构造函数)
    
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
};
  1. Try to use initialization list initialization, because whether you use initialization list or not, for custom type member variables, you must use initialization list initialization first.
class Time
{
    
    
public:
	Time(int hour = 0)
		:_hour(hour)
	{
    
    
		cout << "Time()" << endl;
	}
private:
	int _hour;
};
class Date
{
    
    
public:
	Date(int day)
	{
    
    }
private:
	int _day;
	Time _t;
};
int main()
{
    
    
	Date d(1);
}
  1. The order in which member variables are declared in a class is the order in which they are initialized in the initialization list, regardless 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();
} 

insert image description here

insert image description here

explicit keyword

Constructors can not only construct and initialize objects, but also have the role of type conversion for constructors with a single parameter.

class Date
{
    
    
public:
	Date(int year)
		:_year(year)
	{
    
    }
	explicit Date(int year)
		:_year(year)
	{
    
    }
private:
	int _year;
	int _month:
	int _day;
}void TestDate()
{
    
    
	Date d1(2018);
	// 用一个整形变量给日期类型对象赋值
	// 实际编译器背后会用2019构造一个无名对象,最后用无名对象给d1对象进行赋值
	d1 = 2019;
}

The above code is not very readable. Modifying the constructor with explicit will prohibit the implicit conversion of single-argument constructors.

static member

Concept: A class member
declared as static is called a static member of the class , a member variable decorated with static is called a static member variable ; a member function decorated with static is called a static member function . Static member variables must be initialized outside the class.

【characteristic】

  • 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 without adding the static keyword.
  • Class static members can be accessed using classname::staticmembers or object.staticmembers.
  • Static member functions do not have a hidden this pointer and cannot access any non-static members.
  • Like ordinary members of a class, static members also have access levels of public, protected, and private, and can also have return values.
    insert image description here
    insert image description here【question】
  • Can a static member function call a non-static member function? Can't
  • Can a non-static member function call a static member function of a class? Can

C++11's new way of member initialization

C++11 supports initialization and assignment of non-static member variables when they are declared, but it should be noted that this is not initialization, but the default value for the declared member variable.

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;
}

Tomomoto

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

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 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 to be used normally. So we have to overload operator<< into a global function. But in this case, it will lead to no way to access members outside the class, so friends are needed to solve it. operator>> is the same.

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;
}

A 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 needs to be declared inside the class, and the friend keyword needs to be added when declaring it.

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;
}

【in conclusion】

  • 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
  • Friend functions can be declared anywhere in the class definition, regardless of class access qualifiers
  • A function can be a friend function of multiple classes
  • The calling of friend function is the same as the calling and principle of ordinary function

friend class

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

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 _day;
	Time _t;
};

【in conclusion】

  • Friendship is one-way and not commutative.
  • Friendships are not transitive.

inner class

Concept: If a class is defined inside another class, the inner class is called an inner class. Note that this inner class is an independent class at this time, it does not belong to the outer class, and it is not possible to call the inner class through the object of the outer class. Outer classes don't have any privileged access rights to inner classes.

Note: An inner class is a friend class of an outer class. Note the definition of the friend class, the inner class can access all members of the outer class through the object parameter of the outer class. But the outer class is not a friend of the inner 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());
	return 0;
}

【characteristic】

  • The inner class can be defined in the public, protected and private of the outer class.
  • Note that the inner class can directly access the static and enumeration members of the outer class, without the object/class name of the outer class.
  • sizeof(outer class) = outer class, has nothing to do with inner class.

What is object orientation?

Object Orientation is actually simulating abstraction and mapping the real world.
insert image description here
C++ is an object-oriented program. Object-oriented has three major characteristics: encapsulation, inheritance, and polymorphism.

Guess you like

Origin blog.csdn.net/qq_46994783/article/details/123520807