构造函数
析构函数
构造函数的重载
拷贝构造函数
构造函数
构造函数是一种特殊的成员函数, 别声明为公有成员,其作用是为类的对象分配内存空间,进行初始化。
构造函数的性质:
构造函数的名字必须与类的名字完全相同。
构造函数没有返回值, 不能定义返回类型,包括void型在内。
对象定义时, 编译系统会自动地调用构造函数完成对象内存空间的分配和初始化工作。
构造函数是类的成员函数, 具有一般成员函数所有性质,可以访问所有成员, 可以是内联函数可带有表,可带有默认的形参值,还可重载。
//构造函数实例
class complex
{
private:
double real,imag;//定义复数 实部和虚部
public:
complex(double r, double i)//名字和类名相同
{
real=r;imag=i;//初始化私有数据成员
}
void disp()
{
cout << real<<"+"imag<<"i"<<endl;
}
};
***所有类定义中都会有构造函数**
实际应用中 一般都要给类定义构造函数, 如果没有定义,编译系统就自动生成一个缺省的构造函数,不带有任何参数,仅给对象开辟存储空间, 不完成对数据成员的赋初值, 此时成员数据是随机的。系统自动生成的构造函数的形式为 类名::构造函数名(){}
构造函数的调用
构造函数一般不能被显示地调用, 是在定义对象的同时调用的,其调用的一般格式为:
类名 对象名(实参表)
#include<iostream>
#include<string>
using namespace std;
//构造函数实例
class complex
{
private:
double real,imag;//定义复数 实部和虚部
public:
complex(double r, double i)//名字和类名相同
{
real=r;imag=i;//初始化私有数据成员
}
void disp()
{
cout << real<<"+"<<imag< <"i"<<endl;
}
};
int main()
{
complex ob(1.2,3.4);
ob.disp();
return 0;
}
运行结果:
1.2+3.4i
构造函数几点说明:
构造函数可以是不带参数的, 不带参数的构造函数对对象的初始化是固定的, 如果希望在建立对象时通过参数初始化数据成员, 应该用带参数的构造函数。
#include<iostream>
#include<string>
using namespace std;
//不带参数的构造函数实例
class myclass
{
private:
int a;
public:
myclass();//定义不带参数的构造函数
void disp()
{
cout <<"a^2 = "<<a*a<<endl;
}
};
myclass::myclass()
{
cout<<"initialized\n";a=10;
}
int main()
{
myclass s;//没有小括号 说明调用的是没有参数的构造函数,有参数的话应该在对象后面加上括号
s.disp();
return 0;
}
构造函数可以采用构造初始化表的方法进行初始化。但是如果需要将数据成员存放在堆或者数组当中,则应在构造函数中使用赋值语句,即使构造函数有初始化表也应该如此。
#include<iostream>
#include<cstring>
using namespace std;
//构造函数使用初始化表的实例
class A
{
int i;
float j;
char c;
public:
A(int x, float y, char ch ):i(x),j(y),c(ch)//初始化表 在 : 后面初始化
{}
};
class B
{
int i;
float j;
char c[20];
public:
B(int x,float y,char ch[]):i(x),j(y)//如果是数组的话就必须在函数体内被赋值
{
strcpy(c,ch);
}
};
int main()
{
return 0;
}
对没有定义构造函数的类, 类的公有数据成员可以用初始化表进行初始化。
#include<iostream>
using namespace std;
//没有定义构造函数的类,公有数据成员可以用初始化表进行初始化
class abc
{
public:
char name[10];
int no;
};
int main()
{
abc a={"zhou",1};
cout<<a.name<<" "<<a.no<<endl;
//这种方法适合于结构和数组的初始化
return 0;
}
带有缺省参数的构造函数
当构造函数带有参数时, 在定义对象是必须给构造函数传递参数, 否则构造函数不会被执行。但在实际应用中, 有些构造函数的参数值通常是不变的, 只有在特殊情况下才需要改变它的值,这时,可以将构造函数定义成带缺省参数值的构造函数, 这样,在定义 对象时可以不用指定实参, 用缺省参数值来初始化数据成员。
#include<iostream>
#include<string>
#include<math.h>
using namespace std;
//构造函数实例
class complex
{
private:
double real,imag;//定义复数 实部和虚部
public:
complex(double r=0, double i=0);//带有缺省参数的构造函数
double abscomplex();
};
complex::complex(double r,double i)
{
real = r;
imag = i;
}
double complex::abscomplex()
{
double n;
n =real*real + imag*imag;
return sqrt(n);
}
int main()
{
complex ob1; //没有赋予实参的构造函数 将使用缺省值
complex ob2(1.1);//传递的实参个数小于形参个数的时候 没有获得实际参数的形参将使用缺省值
complex ob3(1.1,2.2);//传递的实参于形参吻合的时候, 将使用实参的值
cout<<"abs of complex ob1 =";
cout<<ob1.abscomplex()<<endl;
cout<<"abs of complex ob2 =";
cout<<ob2.abscomplex()<<endl;
cout<<"abs of complex ob3 =";
cout<<ob3.abscomplex()<<endl;
return 0;
}
*********************************************************
析构函数:
析构函数也是一种特殊的成员函数, 也被声明为公有成员,作用时释放分配空间给对象的内存空间,并做一些善后工作。
析构函数的性质:
析构函数的名字必须是 ~类名
析构函数没有返回值 没有参数, 不能重载;
当对象撤销时,系统会自动调用析构函数完成空间的释放和善后工作;
注意:
每个类都必须有且只有一个析构函数, 若没有显示定义,系统会自动生成一个缺省的空析构函数。
对大多数类而言,缺省的析构函数就能满足要求,但如果对象在完成操作前需要做内部处理,则应显式定义析构函数。
构造函数和析构函数的常见用法就是:构造函数为对象动态申请资源,析构函数释放资源。
#include<iostream>
#include<string>
#include<math.h>
using namespace std;
//构造函数实例
class complex
{
private:
double real,imag;//定义复数 实部和虚部
public:
complex(double r=0, double i=0);//带有缺省参数的构造函数
~complex();//声明析构函数
double abscomplex();
};
complex::complex(double r,double i)
{
cout<<"constructing...."<<endl;
real = r;
imag = i;
}
complex::~complex()//定义析构函数
{
cout<<"destructing...."<<endl;
}
double complex::abscomplex()
{
double n;
n =real*real + imag*imag;
return sqrt(n);
}
int main()
{
complex ob(1.1,2.2);
cout<<"abs of complex ob1 =";
cout<<ob.abscomplex()<<endl;
return 0;
}
程序运行结果:
constructing....
abs of complex ob1 =2.45967
destructing....
******************************************************************
构造函数重载
#include<iostream>
using namespace std;
class point
{
private:
float fx,fy;
public:
point();
point(float x,float y);
void showpoint();
};
point::point()
{
fx=0.0; fy=0.0;
}
point::point(float x,float y=5.5)
{
fx=x;fy=y;
}
void point::showpoint()
{
cout <<fx<<" "<<fy<<endl;
}
int main()
{
point p1;
p1.showpoint();
point p2(10);
p2.showpoint();
point p3(1.1,2.0);
p3.showpoint();
return 0;
}
*****************************************
拷贝构造函数
拷贝构造函数是一个特殊的构造函数,起作用是用一个已经存在的对象初始化本类的新对象。可根据自己的需要定义拷贝构造函数,也可以有系统生成一个缺省的拷贝构造函数。拷贝构造函数没有返回值。拷贝构造函数名与类名相同,但参数是本类对象的引用
自定义拷贝构造函数:
一般形式为:
类名(类名&对象名)
{
//拷贝构造函数的函数体
}
其中,对象名是用来初始化另一个对象的对象的引用。
#include<iostream>
using namespace std;
class point
{
private:
float fx,fy;
public:
point(point &p);//声明拷贝构造函数
point(float x,float y);
void showpoint();
};
point::point(point &p)
{
fx=p.fx+10; fy=p.fy+20;
}
point::point(float x,float y=5.5)
{
fx=x;fy=y;
}
void point::showpoint()
{
cout <<fx<<" "<<fy<<endl;
}
int main()
{
point p1(1.1,2.2);
p1.showpoint();
point p2(p1);
p2.showpoint();
return 0;
}
运行结果:
1.1 2.2
11.1 22.2
缺省的拷贝构造函数:
当用一个已经存在的对象初始化本类的新对象时,如果没有自定义拷贝构造函数,则系统会自动生成一个缺省的拷贝构造函数来完成初始化工作。
拷贝构造函数三种情况下的调用:
用一个对象去初始化本类的另一个对象时。
函数的形参是类的对象, 在进行形参和实参的结合时。
函数的返回值是类的对象,函数执行完返回时。
#include<iostream>
using namespace std;
class point
{
private:
float fx,fy;
public:
point(float x,float y);
void showpoint();
};
point::point(float x,float y=5.5)
{
fx=x;fy=y;
}
void point::showpoint()
{
cout <<fx<<" "<<fy<<endl;
}
int main()
{
point p1(1.1,2.2);
p1.showpoint();
point p2(p1);//用缺省拷贝构造函数创建对象p2
p2.showpoint();
return 0;
}
运行结果:
1.1 2.2
1.1 2.2
#include<iostream>
using namespace std;
class point
{
private:
int x,y;
public:
point(int a=0,int b=0)
{
x=a;y=b;
}
point(point &p);
int getx(){return x;}
int gety(){return y;}
};
point::point(point &p)
{
x=p.x+10;y=p.y+20;
cout<<"调用拷贝构造函数"<<endl;
}
void f(point p)
{
cout<<p.getx()<<" "<<p.gety()<<endl;
}
point g()
{
point q(3,5);return q;
}
int main()
{
point p1(1.1,2.2);
point p2(p1);
cout <<p2.getx()<<" "<<p2.gety()<<endl;
f(p2);
p2 =g();
cout <<p2.getx()<<" "<<p2.gety()<<endl;
return 0;
}
运行结果:
调用拷贝构造函数
11 22
调用拷贝构造函数
21 42
3 5