9——对象的创建和撤销,构造函数和析构函数

时间:2023-01-02 11:27:55
一是构造函数在对象创建时自动调用,用以完成对象成员变量等的初始化及其他操作(如为指针成员动态申请内存空间等); 如果程序员没有显式的定义它,系统会提供一个默认的构造函数。
另一个是析构函数,在对象撤销时自动调用,用以执行一些清理任务,如释放成员函数中动态申请的内存等。 如果程序员没有显式的定义它系统也会提供一个默认的析构函数。 
 
 当对象被创建时,构造函数自动被调用。
        构造函数有一些独特的地方: 函数的名字与类名相同,没有返回类型和返回值,即使是void也不能有
         1> 其主要工作有: 给对象一个标识符。 
         2> 为对象数据成员开辟内存空间。 
          3> 完成对象数据成员的初始化函数体内的工作,由程序员完成)。
上述3点也说明了构造函数的执行顺序, 在执行函数体之前,构造函数已经为对象的数据成员开辟了内存空间,这时, 在函数体内对数据成员的初始化便是顺理成章了。 备注代码给出了point类的显式构造函数 。
 
class point 
{ 
private:    
    int xPos;     
    int yPos; public:     
    point(); 
}; 
point::point() 
{     
    xPos = 0;     
    yPos = 0; 
} 
 
构造函数可以有参数:
 编译器自动生成的缺省(默认)构造函数是无参的,实际上, 构造函数可以接收参数,在对象创建时提供更大的*度,如下列代码
一旦用户定义了构造函数,系统便不再提供默认构造函数。 跟踪执行,理解构造函数的执行顺序。
 
//point.h
#include <iostream> 
using namespace std; 
class point //point类定义,在定义同时实现其成员函数 
{ 
private: //私有成员,分别代表x轴和y轴坐标     
        int xPos;     
        int yPos; 
public:     
        point(int x, int y) //有参构造函数     
        {         
                cout << "对象创建时构造函数被自动调用" << endl;         
                xPos = x;         yPos = y;     
        }     
        void print() //输出信息     
        {         
                cout << "xPos: " << xPos << ",yPos: " << yPos << endl;     
        } 
}; 

#include "point.h" 
int main() 
{ 
        //    point pt0;//错误的调用,因为我们已经显示的定义了一个带参数的构造函数 
        //    pt0.print();//输出pt0的信息     
        point pt1(3, 4);    //调用有参构造函数声明point类变量(类对象)pt1                         	pt1.print();        //输出pt1的信息     
        return 0;
 }  

 

构造函数能够进行重载:
一旦程序员 为一个类定义了构造函数编译器便不会为类 自动生成缺省构造函数
因此, 如果还想使用无参的构造函数,如“point pt1;” 的形式必须在类定义中显式定义一个无参构造函数。 这样,构造函数就会出现两个,会不会有问题呢?不会,构造函数支持重载,在创建对象时,根据传递的具体参数决定采用哪个构造函数。
 

例1

#include <iostream>
using namespace std;

class Point
{
public:
	Point()//构造函数能够进行重载
	{
        	cout << "Point()" << endl;
	} 

	Point(int ix, int iy)
	{
        	cout << "Point(int,int)" << endl;

        	_ix = ix;
        	_iy = iy;
	}

	void print()
	{

		cout << "(" << _ix<< "," << _iy<< ")" << endl;
	}

private:
        int _ix;
        int _iy;
};

int main(void)
{
        Point p1;//调用默认构造函数
        p1.print();
 
        Point p2(3, 4);
        p2.print();

        return 0;
}
例2
//point1.h
#include <iostream> 
using namespace std; 
class point //point类定义,在定义同时实现其成员函数 
{ 
public:     
        point(int x, int y)//有参构造函数     
        {         
                cout << "有参构造函数的调用" << endl;         
                xPos = x;         
                yPos = y;     
        }     
        point() //无参构造函数     
        {         
                cout << "无参构造函数的调用" << endl;         
                xPos = 0;         
                yPos = 0;            
        }     
        void print()//输出信息     
        {         
                cout << "xPos: " << xPos << ",yPos: " << yPos << endl;     
        } 
private: //私有成员,分泌诶代表x轴和y轴坐标     
        int xPos;     
        int yPos; 
};
#include "point1.h" 
int main() 
{     
        point pt1(3, 4);    //调用有参构造函数声明point类变量(类对象)pt1                         pt1.print();        //输出pt1的信息     
        point pt2;            //调用无参构造函数声明point类变量(类对象)pt2                         pt2.print();        //输出pt2的信息     
        return 0;
}  

  

------------------
构造函数允许按参数缺省方式调用
上例中的构造函数可以作如下定义:
point(int x=0,int y=0) 
{ 
        cout<<"对象创建时构造函数被自动调用"<<endl; 
        xPos=x; 
        yPos=y; 
} 
此时,可在创建对象时省略参数,下列语句都是合法的: 
       
 	point pt;    //x和y都采用默认值0 
        point pt(3);    //x为3,y采用默认值0 
        point pt(3,4);//x为3,y为4,两个参数都不采用默认值
 
初始化表达式1
        除了在构造函数体 初始化数据成员 外,还可以 通过成员初始化表达式来完成
        成员初始化表可用于初始化类的任意数据成员(后面要介绍的static数据成员除外),
         该表达式逗号分隔的数据成员表组成初值放在一对圆括号中
 
        只要 将成员初始化表达式放在构造函数的头和体之间并用冒号将其与构造函数的头分隔开,便可实现数据成员表中元素的初始化 
 
point(int x,int y)
{ 
        cout<<"有参构造函数的调用"<<endl; 
        xPos=x; 
        yPos=y; 
} 
//等价于: 
point(int x,int y)
:xPos(x)
,yPos(y) 
{     
        cout<<"有参构造函数的调用"<<endl; 
}
 
--------------------------
初始化表达式2 
        每个成员在初始化表中只能出现一次 
        初始化的顺序不是由成员变量在初始化表中的顺序决定的
         而是由成员变量在类中被声明时的顺序决定的。(即在private中声明的顺序)
        理解这一点有助于避免意想不到的错误。
 
//point.h
#include <iostream> 
using namespace std; 
class point 
{ 
private:     
        int yPos;    //先定义     
        int xPos;    //后定义 
public:     
        point(int x)
        :xPos(x)
        , yPos(xPos) //初始化表取决于成员声明的顺序     
        //如果换成
        //:yPos(y)
        //,x(yPos)//这样的话,x先初始化,但是这时yPos还没有初始化,x就是不确定的值了
        {     
        }     
        void print()     
        {         
                cout << "xPos: " << xPos << ", yPos: " << yPos << endl;     
        } 
}; 
#include "point.h" 
int main() 
{     
        point pt1(3);        //调用有参构造函数声明变量pt1     
        pt1.print();         
        return 0; 
}  

  

 
例子:
#include <iostream>
using namespace std;

class Point
{
public:
#if 0
    Point()//构造函数能够进行重载
    {
        cout << "Point()" << endl;
    }
#endif
 
    Point(int ix, int iy)
    : _ix(ix)//初始化列表
    , _iy(iy)
    {
        cout << "Point(int,int)" << endl;
        //_ix = ix;//赋值
        //_iy = iy;
    }
    void print()
    {
        cout << "(" << _ix
             << "," << _iy
             << ")" << endl;
    }
private:
    int _ix;
    int _iy;
};
 
int main(void)
{
    Point p1;//调用默认构造函数
    p1.print();
 
    Point p3(5);
    p3.print();
 
    Point p2(3, 4);
    p2.print();
 
    return 0;
}