关闭

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

112人阅读 评论(0) 收藏 举报

this指针的特性:

1)this指针的类型是一个类类型 * const, 这表示什么呢?this指针的指向不能被改变。

2)this指针本身不占用大小,它并不是对象的一部分,在使用sizeof时候 不算长度。

3)this指针是类成员函数的第一个默认隐含参数,并不需要显示的输入,系统默认隐藏。

4)只有在类的非静态成员函数中调用,其他任何函数都不可以。

//因为静态成员属于类的,而不属于某个特定的对象。一个对象有属于自己的this指针,但是属于类的静态成员是没有this指针的。

5)  thiscall调用约定:
    a、参数从右向左压栈。
    b、如果参数个数确定,this指针通过ecx传递给被调用者;如果参数不确定,this
       指针在所有参数被压栈后压入堆栈。
    c、对参数个数不定的,调用者清理堆栈,否则函数自己清理堆栈

6)this指针不能再初始化列表之中使用,在初始化列表之中,类的对象还没有创建,编译器不知道对象的结构就不知道 分配多大的空间。

\

一、构造函数
  1、函数名与类名相同。
  2、没有返回值。
  3、有初始化列表(可以不用)。
  4、新对象被创建,由编译器自动调用,且在对象的生命期内仅调用一次。
  5、构造函数可以重载,实参决定了调用那个构造函数。
  6、如果没有显示定义时,编译器会提供一个默认的构造函数。
  7、无参构造函数和带有缺省值得构造函数都认为是缺省构造函数,并且缺省构造函数只能有一个。
  8、构造函数不能用const来修饰,因为构造函数要改变参数的内容。

再来看一下构造函数的特性:


首先构造函数允许重载, 最为常见的构造函数的重载就是我们所熟知的拷贝构造函数。不但如此,你也可以显示的定义你的构造函数,如:Date(){} 里面可以什么也不写,这就是一个最简单的构造函数(什么也不写的构造还函数,你可以去看汇编代码,还是做了些事情的),只要你满足重载的条件(不过要注意 会不会产生二义性),你可以定义多个构造函数(通过参数可以选出你所要调用的构造函数)。当然如果你什么也没有写,那么编译器就会帮你自动生成一个构造函 数,当然这个构造函数也不会帮你做什么。


构造函数有两种缺省构造函数:

1.无参数的缺省构造函数。参数列表中什么都没有。

2.全缺省构造函数。参数列表中的参数都给一个默认值

但这两种缺省函数只能明确的显示一个,这样,当你再给一个空参数的情况下,两个函数都可以调用。不知道具体调用哪一个了。

【初始化列表】
  初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个数据
  成员后面跟一个放在园括号中的初始化式。
 【初始化顺序】
  1、每个成员在初始化列表中只能出现一次。并不能对一个变量初始化两次。
  2、初始化列表仅用于初始化数据成员,并不指定这些数据成员的初始化顺序,
     数据成员在类中定义顺序就是在参数列表中的初始化顺序。
  3、尽量避免使用成员初始化成员,成员的初始化顺序最好和成员的定义顺序保持一致。

    以下几种情况时必须使用初始化列表

    1.常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面
2.引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面
3.没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化

构造函数的作用:

1)构造对象 

2)初始化对象 

3)类型转化(必须是单参)

默认构造函数

当你没有显示定义一个构造函数的时候。编译器会帮你自动定义一个构造函数。不过这个构造函数什么都不做。但是如果你显示的定义了一个构造函数,即使这个构造函数什么都不做,编译器也不会自动定义默认构造函数。

二、拷贝构造函数 Data(const Data& d)

只有单个形参,而且该形参是对本类类型对象的引用(常用const修饰),这样的构造函数称为拷贝构造函数。拷贝构造函数是特殊的构造函数,创建对象时使 用已存在的同类对象来进行初始化,由编译器自动调用。
当使用拷贝构造函数的时候参数要传递本类类型的引用,如果传值的方式,会在过程中创建一个临时变量,会调用拷贝构造函数,循环往复,无限调用拷贝构造函数,行程无限递归。
拷贝构造函数是构造函数的重载。
当拷贝构造函数没有显示定义的时候,编译器会默认的合成一个拷贝构造函数,依次的拷贝数据成员。
  【使用场景】
   1、对象实例化对象
      CDate d1(1990, 1, 1);
      CDate d2(d1);
   2、传值方式作为函数的参数
      void FunTest(const CDate date)
      {}
   3、传值方式作为函数返回值
      CDate FunTest()
      {
           CDate date;
           return date;
      }

三、析构函数

      析构函数:与构造函数功能相反,在对象被销毁时,由编译器自动调用,完成类的一些资源清理和汕尾工作。在使用析构函数的时候,顺序是先进后出,后面运行的先析构。
class CArray
{
public:
        CArray(size_t capacity)
                : _capacity(capacity)
        {
                _pData = ( int*)malloc(capacity*sizeof (int));
                _size = 0;
        }
        ~CArray()
        {
                 if (NULL != _pData)
                {
                        free(_pData);
                        _pData = NULL;
                }
                _size = 0;
                _capacity = 0;
        }
private:
         int* _pData;
        size_t _size;
        size_t _capacity;
};

构函数的特点:

1)一个类里面只有一个,对象被销毁的时候只调用一次。

2)不能有参数,也不能有返回值,因此析构函数不能重载

3)如果没有显示的给出,编译器会默认生成一个。

4)在对象生命周期结束的时候,由编译器自动调用。

5)析构函数在函数体内并不是删除对象,而是做一些清理工作。

四、运算符的重载(后三个默认函数)

在这里提到了运算符重载,于是我把后面的三个重载放在一起讲。先来了解一下什么叫做运算符重载(或者叫做操作符重载),重载操作符是具有特殊函数名的函 数,关键字operator后面接需要定义的操作符符号。操作符重载也是一个函数,具有返回值和形参表。它的形参数目与操作符的操作数目相同,函数调用操 作符可以接受任意数目的操作数。

可以被重载的操作符:

\

不可以被重载的操作符:

\

1、不能通过连接其他符号来创建新的操作符:比如operator@;
void operator @(){}

2、重载操作符必须有一个类类型或者枚举类型的操作数

?
1
2
3
4
5
6
7
8
9
10
1. int operator +(const int _iNum1 , const int _iNum2 )   // 报错 
2. { 
3.     return ( _iNum1 + _iNum2); 
4. } 
5.  
6. typedef enum TEST {one ,two ,three }; 
7. int operator+(const int _iNum1 , const TEST _test ) 
8. { 
9.      return _iNum1; 
10. } 
3、用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义

4、重载前后操作符的优先级和结合性是不变的


5、不在具备短求值特性重载操作符不能保证操作符的求值顺序,在重载&&和||中,对每个操作数
都要进行求值,而且对操作数的求值顺序不能做规定,因此:重载&&、 ||和逗号操作符不是好的做法。

6、作为类成员的重载函数,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参。

?
1
2
3
4
5
6
7
8
9
CTest operator+(const CTest test1, const CTest test2)const   // 报错 
     return test1; 
   
CTest operator+(const CTest test1)const 
     return test1; 
7、一般将算术操作符定义为非成员函数,将赋值运算符定义成员函数
8、操作符定义为非类的成员函数时,一般将其定义为类的友元
9、== 和 != 操作符一般要成对重载
10、下标操作符[]:一个非const成员并返回引用,一个是const成员并返回引用
11、解引用操作符*和->操作符,不显示任何参数
13、自增自减操作符
前置式++/--必须返回被增量或者减量的引用
后缀式操作符必须返回旧值,并且应该是值返回而不是引用返回
14、输入操作符>>和输出操作符<<必须定义为类的友元函数
下面简单的列出一些操作符的重载

Complex::Complex( double real=0.0 ,  double image=0.0)
{
_dReal = real;
_dImage = image;
}


Complex::Complex(const Complex& complex)
{
_dReal = complex._dReal;
_dImage = complex._dImage;
}
Complex&Complex:: operator=(const Complex& complex)
{
if (this != &complex)
{
_dReal = complex._dReal;
_dImage = complex._dImage;
}
return *this;
}


Complex Complex:: operator+(const Complex& complex)
{
Complex ret(_dReal + complex._dReal, _dImage + complex._dImage);
return ret;
}


Complex Complex:: operator-(const Complex& complex)
{
Complex ret(_dReal - complex._dReal, _dImage - complex._dImage);
return ret;
}


Complex Complex:: operator*(const Complex& complex)
{
Complex ret(_dReal*complex._dReal - _dImage*complex._dImage, _dReal*complex._dImage + _dImage*complex._dReal);
return ret;
}


Complex Complex::operator/(const Complex& complex)
{
Complex ret((_dReal * complex._dReal + _dImage * complex._dImage) / (complex._dReal * complex._dReal + complex._dImage * complex._dImage),
(complex._dReal * _dImage - _dReal * complex._dImage) / (complex._dReal * complex._dReal + complex._dImage * complex._dImage));
return ret;
}


Complex& Complex::operator+=(const Complex& complex)
{
_dReal += complex._dReal;
_dImage += complex._dImage;
return *this;
}


Complex& Complex::operator+=(const Complex& complex)
{
_dReal -= complex._dReal;
_dImage -= complex._dImage;
return *this;
}


Complex&  Complex::operator*=(const Complex& complex)
{
double temp = 0.0;
temp = _dReal;
_dReal = (_dReal*complex._dReal - _dImage *complex._dImage);
_dImage = (temp * complex._dImage + _dImage * complex._dReal);
return *this;
}
Complex&  Complex::operator/=(const Complex& complex)
{
double temp = 0.0;
temp =_dReal;
_dReal = (_dReal * complex._dReal + _dImage * complex._dImage) / (complex._dReal * complex._dReal + complex._dImage * complex._dImage);
_dImage = (complex._dReal * _dImage - temp * complex._dImage) / (complex._dReal * complex._dReal + complex._dImage * complex._dImage);
return *this;
}


bool Complex:: operator >(const Complex& complex)
{
bool flag;
double num1 = _dReal * _dReal + _dImage * _dImage;
double num2 = complex._dReal * complex._dReal + complex._dImage * complex._dImage;
if (num1 > num2)
{
flag = true;
}
else
{
flag = false;
}
return flag;
}
bool Complex:: operator >=(const Complex& complex)
{
bool flag;
double a = _dReal * _dReal + _dImage * _dImage;
double b = complex._dReal * complex._dReal + complex._dImage * complex._dImage;
if (a >= b)
{
flag = true;
}
else
{
flag = false;
}
return flag;
}
bool Complex:: operator <(const Complex& complex)
{
bool flag;
double a = _dReal * _dReal + _dImage * _dImage;
double b = complex._dReal * complex._dReal + complex._dImage * complex._dImage;
if (a < b)
{
flag = true;
}
else
{
flag = false;
}
return flag;
}
bool Complex::operator <=(const Complex& complex)
{
bool flag;
double a = _dReal * _dReal + _dImage * _dImage;
double b = complex._dReal * complex._dReal + complex._dImage * complex._dImage;
if (a <= b)
{
flag = true;
}
else
{
flag = false;
}
return flag;
}
bool Complex:: operator ==(const Complex& complex)
{
bool flag;
double a = _dReal * _dReal + _dImage * _dImage;
double b = complex._dReal * complex._dReal + complex._dImage * complex._dImage;
if (a == b)
{
flag = true;
}
else
{
flag = false;
}
return flag;
}
bool Complex:: operator !=(const Complex& complex)
{
bool flag;
double a = _dReal * _dReal + _dImage * _dImage;
double b = complex._dReal * complex._dReal + complex._dImage * complex._dImage;
if (a != b)
{
flag = true;
}
else
{
flag = false;
}
return flag;
}

 

用的是C++编译器

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:113次
    • 积分:11
    • 等级:
    • 排名:千里之外
    • 原创:1篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章存档