四、实验结论
- 验证性实验部分
总结你对类、对象、构造函数、复制构造函数、析构函数的认识、理解和思考。
类与对象:
对象是对客观事物的抽象,类是对对象的抽象。
(1)类类型的声明:
class 类名
{
public:
公用的数据和成员函数
protected:
保护的数据和成员函数
private:
私有的数据和成员函数
}
(2)什么是构造函数?
通俗的讲,在类中,函数名和类名相同的函数称为构造函数。它的作用是在建立一个对象时,作某些初始化的工作(例如对数据赋予初值)。C++允许同名函数,也就允许在一个类中有多个构造函数。如果一个都没有,编译器将为该类产生一个默认的构造函数。此默认构造函数的功能是为对象分配内存,但无法为成员数据赋初值。 构造函数上惟一的语法限制是它不能指定返回类型,甚至void 也不行。
用于在创建对象时为对象分配内存 ,并可以将其初始化到特定的状态。
1,不带参数的构造函数:一般形式为: 类名 对象名(){函数体}
2,带参数的构造函数:不带参数的构造函数,只能以固定不变的值初始化对象。带参数构造函数的初始化要灵活的多,通过传递给构造函数的参数,可以赋予对象不同的初始值。
一般形式为:构造函数名(形参表); 创建对象使用时:类名 对象名(实参表);
如果类中没有写构造函数,编译器会自动生成一个隐含的默认构造函数,该函数是个空值。
小结: 构造函数的重载
构造函数用于在创建对象时为对象分配内存 ,并可以将其初始化到特定的状态,是特殊的成员函数。
与普通函数类似,构造函数也可以被重载。
① 在一个类的定义中,可以包含多个构造函数。这些构造函数有相同的函数名称,但具有不同的形参列表。
② 定义对象时,编译器会根据参数的个数、类型来决定调用哪一个重载构造函数。
③ 当重载不带参数的构造函数和带默认形参值的构造函数时,程序可能会产生二义性。因此,在实际编程中应避免这一情形。
(3)析构函数:
当一个类的对象离开作用域时,析构函数将被调用(系统自动调用)。析构函数的名字和类名一样,不过要在前面加上 ~ 。对一个类来说,只能允许一个析构函数,析构函数不能有参数,并且也没有返回值。析构函数的作用是完成一个清理工作,如释放从堆中分配的内存。
一个类中可以有多个构造函数,但析构函数只能有一个。对象被析构的顺序,与其建立时的顺序相反,即后构造的对象先析构。
(4)复制构造函数:
① 是特殊的构造函数: 其形参是本类对象的引用
② 复制构造函数在下述情形被调用:
使用已有的对象初始化一个新的对象
复制构造函数有且只有一个形参,而且这个形参必须是本类对象的引用。
在C++中,下面三种对象需要调用拷贝构造函数(有时也称“复制构造函数”):
- 一个对象作为函数参数,以值传递的方式传入函数体;
- 一个对象作为函数返回值,以值传递的方式从函数返回;
- 一个对象用于给另外一个对象进行初始化(常称为赋值初始化);
如果类中没有写复制构造函数,编译器会自动生成一个隐含的复制构造函数,功能是把初始值对象的每个数据成员的值都复制到新建立的对象中。
通常的原则是:①对于凡是包含动态分配成员或包含指针成员的类都应该提供拷贝构造函数;②在提供拷贝构造函数的同时,还应该考虑重载"="赋值操作符号。
class 类名
{
public:
类名(形参表) ; // 构造函数
类名(类名 &对象名); // 复制构造函数
…
}
类名::类名(类名 &对象名)
{
…
}
ps:用已存在对象初始化该类的另一个对象,两种方法:1)Clock hisclock(myclock); <复制函数会被调用> 2)Clock hisclock = myclock;<复制函数不被调用>
//4-11.定义并实现一个 矩形类,有长,宽两个属性,由成员函数计算矩形的面积//
#include<iostream>
using namespace std;
class Rectangle{ //声明定义类rectangle及其数据和方法
public: //外部接口
Rectangle(float a,float b); //构造函数<带有参数a,b--长,宽>
float rectanglearea(); //计算矩形的面积
private: //私有数据成员
float Length,width; //长,宽
};
//类的实现
//构造函数初始化数据成员a,b
Rectangle::Rectangle(float a,float b){
Length=a;
width=b;
}
//计算矩形的面积
float Rectangle::rectanglearea() {
return Length*width;
}
//主函数实现
int main(){
float Length,width;
cout<<"Enter the Length and width of the rectangle:" ; //提示用户输入长,宽
cin>>Length>>width;
class Rectangle c(Length,width); //定义的类的对象---矩形c
cout<<"The area of Retangle is:"<<c.rectanglearea()<<endl; //输出矩形面积
return 0;
}
//定义类的对象时,没加class就显示我是错误的
//4-20,定义一个负数类Complex,使得下面的代码能够工作。
//Complex c1(3,5); ---用复数3+5i初始化c1
//Complex c2=4.5; ---用实数4.5初始化c2
//c1.add(c2); ---将c1与c2相加,结果保存在c1中
//c2.show();---将c1输出(这时的结果应该是7.5+5i)
#include<iostream>
using namespace std;
class Complex{
public:
Complex(double r0,double i0); //用户自定义的构造函数<带有两个参数>
Complex(double r0); //同上,<带有一个参数 >
Complex(Complex &c0); //用户自定义的复制构造函数---形参必须是该类对象的引用
void add(Complex &c0); //同上
void show(){cout<<real<<"+" <<imaginary<<"i"<<endl; } //函数体的实现在类内部,是内联成员函数
private:
double real;
double imaginary;
};
//类的实现
Complex::Complex(double r0,double i0){
real=r0;
imaginary=i0;
}
Complex::Complex(double r0){ //这两个可以合并在一起,只用一个构造函数《下面的改成c2(4.5,0)》
real=r0;
imaginary=0;
}
Complex::Complex(Complex &c0){
real=c0.real;
imaginary=c0.imaginary;
}
void Complex::add(Complex &c0){ // 此处声明会引用到类的对象,实现对象间的运算?不是太理解
real+=c0.real;
imaginary+=c0.imaginary;
}
//主函数的实现
int main()
{
Complex c1(3,5); //定义Complex类的对象c1
Complex c2(4.5); // 定义Complex类的对象c2
c1.add(c2); //进行add运算--c2的值加到c1里面
c1.show(); //执行show函数--以我要求的形式输出
return 0;
}
1,操作还不是太熟练,2,析构函数只知道摆在类里面 ~类名,但是下面就不知道怎么用它。3,复制构造函数的原理