类和六个默认函数及this指针

原创 2016年06月01日 13:30:12

类是c++中的一种自定义类型,用关键字class,来进行定义,很像C语言中的结构体但又有不同

class Date
{
	int _year;
	int _month;
	int _day;
	double _data;
};


这是一个最简单的类,类中的成员变量类型可以各不相同,不同于结构体的是,类中成员的默认属性为私有(private),在类外不能对类的成员变量进行访问,形成一种封装,是对成员变量的一种保护。在类中还可以声明或定义一些成员函数,一般用public限定为公有属性,在类外可以对成员函数进行调用,在类外定义函数时需在类中声明函数,定义时在函数名前加上类名和域运算符"::"

class Date
{	
public:
void Fun1()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};



在类的成员函数中可以访问类的成员变量,实际上是通过一个指向类对象的指针实现的,称为this,调用函数时编译器自动传递了这个this指针作为一个参数给被调用函数,this指针始终指向本类对象,this指针和类成员函数不属于类,不影响sizeof(类名)的结果。上述代码在编

class Date
{
public:
void Fun1()
	{
		cout <<this->_year << "-" <<this-> _month << "-" <<this->_day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};



类存在6个默认的成员函数,若未显示定义,编译器会自动合成



构造函数:类的一个特殊成员函数,不需要返回值,函数名和类名相同,在类对象被创建时自动调用构造函数,进行类对象的一些初始化工作,若未显示定义则由编译器自动合成,构造函数有初始化列表但可以不使用,构造函数分为初始化阶段和普通计算阶段,初始化的顺序与变量在类中的定义顺序一致,与初始化列表的顺序无关,所以一般不宜用一个变量初始化另一个变量。另外,构造函数可以进行重载,具体调用哪个构造函数根据所给参数决定,

class Date
{
public:
	Date()                                                       //构造函数1
		:_year(2016)
		, _month(10)
		, _day(10)
	{}                                          
	Date(int year = 2016, int month = 6, int day = 1)             //构造函数2
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date()" << endl;
	}                                                                                                                  private:
	int _year;
	int _month;
	int _day;
};


在函数体内可进行编写者想要的操作,另外,编译器自动合成的构造函数给类成员变量赋随机值,若类只含有一个成员变量,则进行隐式转换,将成员类型隐式转换为一个类类型,用类创建对象时可直接对对象进行赋值。此时构造函数又可称为转换构造函数。

对构造函数总结一下:

1、函数名与类名相同
2、不需要返回值
3、有初始化列表,(可以不用)
4、新对象被创建时,编译器自动调用构造函数,对象生命周期内仅调用一次
5、若未显示定义,编译器自动合成构造函数
6、构造函数可以重载,实参决定调用哪个构造函数
7、无参或全缺省的构造函数都被认为是缺省的构造函数,缺省构造函数只能有一个
8、构造函数不能使用const修饰(无法修改成员变
9、若类中只有一个成员变量,城建对象时可直接对对象进行赋值,编译器自动将赋值内容隐式转换为类类型,若要防止这种隐式转换,可用关键字explicit对构造函数进行修饰     
10、构造函数的作用:(1)构建对象那 (2)初始化对象(3)进行类型转换:(1)构建对象那 (2)初始化对象(3)进行类型转换



接下来是拷贝构造函数,首先它也是一个构造函数,拥有构造函数的特性,在使用对象来创建对象时调用,拷贝构造函数也不需要返回值,函数名与类名相同,有一个参数,为同类对象的引用,一般用const对其修饰,防止对此对象进行修改,简单说拷贝构造函数的作用就是进行对一个对象的拷贝

class Date
{
public:
	Date()                                                       //构造函数1
		:_year(2016)
		, _month(10)
		, _day(10)
	{}                                          
	Date(int year = 2016, int month = 6, int day = 1)             //构造函数2
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date()" << endl;
	}
	Date(const Date& A)                                           //拷贝构造函数                                                             
	{
		cout << "Date(const Date& A)" << endl;
	}                                                                                                                                  
private:
	int _year;
	int _month;
	int _day;
};

总结:

  1、是构造函数的重载,拥有构造函数的一些特性(返回值,函数名,函数组成)
  2、函数参数必须使用同类型对象的引用传递。   
  3、如果没有显式定义,系统会自动合成一个默认的拷贝构造函数。默认的拷贝构造函数会依次拷贝类的数据成员完成初始化。
 

析构函数,作用与构造函数刚好相反,在对象呗销毁时由编译器自动调用,完成类的一些资源清理和汕尾工作,类生命周期内仅调用一次,同样没有返回值,函数名为类名前加"~"

class Date
{
public:
	Date()                                                       //构造函数1
		:_year(2016)
		, _month(10)
		, _day(10)
	{}                                          
	Date(int year = 2016, int month = 6, int day = 1)             //构造函数2
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date()" << endl;
	}
	Date(const Date& A)                                           //拷贝构造函数
		:_year(A._year)
		, _month(A._month)
		, _day(A._day)
	{
		cout << "Date(const Date& A)" << endl;
	}
	~Date()                                                       //析构函数
	{
		cout << "~Date" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

总的来说析构函数比较简单,总结一下:

1、析构函数在类名加上字符~。
 2、析构函数无参数无返回值。
 3、一个类有且只有一个析构函数。若未显示定义,系统会自动生成缺省的析构函数。
 4、对象生命周期结束时,C++编译系统系统自动调用析构函数。
 5、析构函数体内并不是删除对象,而是做一些清理工作。


除了以上三个函数,还有一个与类有关的函数不得不提:友元函数

友元函数是定义在类外的普通函数,在类中加friend修饰为类的友元函数,在友元函数中可访问类的私有成员,但友元函数不属于类的的成员函数,所以不受public以及private限定,也不存在默认的this指针。写一个友元函数

class Date
{
public:
	Date()                                                       //构造函数1
		:_year(2016)
		, _month(10)
		, _day(10)
	{}                                          
	Date(int year = 2016, int month = 6, int day = 1)             //构造函数2
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date()" << endl;
	}
	Date(const Date& A)                                           //拷贝构造函数
		:_year(A._year)
		, _month(A._month)
		, _day(A._day)
	{
		cout << "Date(const Date& A)" << endl;
	}
	~Date()                                                       //析构函数
	{
		cout << "~Date" << endl;
	}
friend void Fun3(const Date& B);                                      //友元函数
private:
	int _year;
	int _month;
	int _day;
	double _data;
};


void Fun3(const Date& B)
{
	cout << "friend " << B._year << B._month << B._day << endl;
}

友元函数必须在类中声明,在类外定义。友元函数可以提高程序的运行效率,但会破坏程序的封装和隐蔽。总结一下友元函数:

1、友元函数可访问类的私有成员,但不是类的成员函数;
2、友元函数可以在类定义的任何地方声明,不受类访问限定符限制;
3、一个函数可以是多个类的友元函数;
4、友元函数的调用与普通函数的调用和原理相同;                                                                                             5、友元关系不能传递;  
6、友元关系是单向的,不具有交换性.


操作符重载:操作符重载是具有特殊函数名的函数,关键字opreator后加要进行重载的操作符,操作符重载也是一个函数,具有返回值和形参表。它的形参数目与操作符的操作数目相同,函数调用操作符可以接受任意数目的操作数。类的赋值操作符重载和取址操作符重载时类的两个默认成员函数,若编写者未进行定义也可调用,要对类进行其他的操作符运算则必须进行操作符重载,重载符号必须是现有的一些操作符,除以下五个操作符以外都可进行操作符重载:

1、 .                  成员选择符     

2、.*                 成员对象选择符

3、::                  域运算符

4、 ?:                条件操作符

5、 sizeof        


下面对日期类的"+"运算符,"="运算符,"-"运算符以及"<<"进行重载:
class Date
{
public:
	Date()                                                       //构造函数1
		:_year(2016)
		, _month(10)
		, _day(10)
	{}                                          
	Date(int year = 2016, int month = 6, int day = 1)             //构造函数2
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date()" << endl;
	}
	Date(const Date& A)                                           //拷贝构造函数
		:_year(A._year)
		, _month(A._month)
		, _day(A._day)
	{
		cout << "Date(const Date& A)" << endl;
	}
	~Date()                                                       //析构函数
	{
		cout << "~Date" << endl;
	}
	Date operator-(int days);
	Date operator+(int days);
	Date& operator=(const Date& d);
	friend ostream& operator<<(ostream& os, const Date& d);
	friend void Fun3(const Date& B);
	bool IsLeap();                                                  //判断是否为闰年
private:
	int _GetMonthDay(int month);                                    //获取当月天数

private:
	int _year;
	int _month;
	int _day;
	double _data;
};

bool Date::IsLeap()
{
	if ((_year % 4 == 0 && _year % 100 != 0) ||
		(_year % 400 == 0))
	{
		return true;
	}
	return false;
}

ostream& operator<<(ostream& os, const Date& d)
{
	os << d._year << "-" << d._month << "-" << d._day;
	return os;
}

int Date::_GetMonthDay(int month)
{
	int day[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	if (IsLeap() == 1 && month == 2)
	{
		return day[month] + 1;
	}
	return day[month];
}

Date& Date::operator=(const Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
	return *this;
}
Date Date::operator+(int days)
{
	_day = _day + days;
	while (_day > _GetMonthDay(_month))
	{
		_day = _day - _GetMonthDay(_month);
		_month++;
		if (_month == 13)
		{
			_month = 1;
			_year++;
		}
	}
	Date Tmp = *this;
	return Tmp;
}
Date Date::operator-(int days)
{
	_day = _day - days;
	while (_day < 1)
	{
		_month--;
		_day = _day + _GetMonthDay(_month);
		if (_month == 1)
		{
			_month = 12;
			_year--;
		}
	}
	Date tmp = *this;
	return tmp;
}

运算符重载后 可直接调用于类的一些操作,如赋值、输出、日期加天数等,操作符左侧为当前对象,操作符后为参数。总结一下运算符重载:
1、不能通过连接其他符号来创建新的操作符:比如operator@;
   void operator @(){},这样是错误的
2、重载操作符必须有一个类类型或者枚举类型的操作数
3、用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义
5、不在具备短求职特性
   重载操作符不能保证操作符的求职顺序,在重载&&和||中,对每个操作数都要进行求值,而且对操作数的求职顺序不能做规定,因此:重载&&、||和逗号操作符不是好的做法。
6、作为类成员的重载函数,其形参看起来比操作数数目少1, 成员函数的操作符有一个默认的形参this,限定为第一个形参。
7、一般将算术操作符定义为非成员函数,将赋值运算符定义成员函数
8、操作符定义为非类的成员函数时,一般将其定义为类的友元
9、== 和 != 操作符一般要成对重载
10、下标操作符[]:需要定义两个重载函数,一个非const成员并返回引用,一个是const成员并返回引用,这样可以防止不必要的操作失误;
11、解引用操作符*和->操作符,不显示任何参数
13、自增自减操作符
    前置式++/--必须返回被增量或者减量的引用
    后缀式操作符必须返回旧值,并且应该是值返回而不是引用返回
14、输入操作符>>和输出操作符<<必须定义为类的友元函数,否则参数顺序就要颠倒成为 (类名)<<cout:










版权声明:本文为博主原创文章,未经博主允许不得转载。

C++之中this指针与类的六个默认函数小结

我们先来看看this指针。之前看过一篇关于this指针的文章,觉得写的很好,今天决定自己来写一写,顺便总结一下C++里面关于类的一些内容。        什么是this指针呢?简单的说它是一个指向类的...

浅谈类的六个默认成员函数和隐含的this指针

今天简单的浅谈一下关于类和对象的一些基础认识!      类的六个默认成员函数:构造函数、拷贝构造、析构函数、赋值操作符重载、取地址操作符重载和const修饰的取地址操作符重载。     构造...
  • L__xing
  • L__xing
  • 2017年10月21日 18:17
  • 201

类和对象 , 四个默认成员函数及运算符重载 , 隐含的this指针

C++入门知识(2):1:类和对象:类(class):类的定义:类(class)实际上是一种高度抽象化的东西,百度上对类的定义是:类的实质是一种数据类型,类似于int、char等基本类型,不同的是它是...

C++ 7.7 类的成员函数、this 指针、默认构造函数、默认初始化(总结)

简介 ================================================================================================...

小结 | C++(二)| 默认成员函数、this指针

四个默认成员函数、隐藏的this指针

C++与C#对比学习:函数(二)返回值,默认实参.this指针

函数返回值 我们定义函数时会指定一个返回值类型,那在函数体中必须返回一个匹配的类型,或者隐式转换后能匹配的类型.不过有时存在这样的情况,如果函数体中存在一些分支语句,有些情况是可以返回一个值,但有时...

C++类中的六个默认函数(一)

C++中类的6个默认函数中的构造函数,拷贝构造函数和析构函数
  • if9600
  • if9600
  • 2017年03月19日 22:39
  • 412

类的六个默认成员函数

类中,默认生成六个成员函数: 构造函数 拷贝构造函数 析构函数 赋值运算符重载 取地址(&)运算符重载 const修饰的取地址运算符重载...

C++:对象数组、对象动态申请和释放、类的定义和实现分开、this指针、常成员函数、时钟

一、对象数组的定义和初始化 1. 对象数组的创建方法:   //常量都是无名对象 1)类类型 数组名[元素个数]; 2)类类型 数组名[元素个数] = { 数组的初始化列表... }; 2. ...

C++的一些小总结 类 静态成员变量/函数 this指针

C++总结之一 比较是学习的一个很有效的方法。c 被认为是最贴近机器语言和执行效率最高的语言,语法规则也不复杂。关于C的知识就懒得写了。 C++是在c的基础上扩展了很多。现在就比...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:类和六个默认函数及this指针
举报原因:
原因补充:

(最多只允许输入30个字)