构造函数2

摘要:
构造函数创建类对象,初始化其成员,析构函数撤销类对象。构造函数和析构函数是类的特殊成员函数,他们的设计与应用,直接影响编译程序处理对象的方式。构造函数和析构函数的实现使C++的类机制得以充分显示。因此,在桌子对象建立时,构造函数的任务是赋予一组值给该桌子对象。这些工作由构造函数来完成。

C++的构造函数和析构函数,使类的对象能够轻易的被创建和撤销。构造函数创建类对象,初始化其成员,析构函数撤销类对象。构造函数和析构函数是类的特殊成员函数,他们的设计与应用,直接影响编译程序处理对象的方式。构造函数和析构函数的实现使C++的类机制得以充分显示。所以本章内容是C++的重点之一。

学习了本章之后,要求理解类与对象的区别,掌握定义构造函数和析构函数的方法,把握默认构造函数的意义,了解类成员初始化的问题,掌握构造类成员的方法。

1、类与对象:

一个类是描述一类型的事物,描述这些事物所应具有的属性,如人有身长,体重,文化,性别,年龄,等。

一个对象是类的一个实例,它具有确定的属性。

人类只有一个,人类的实例就会有无数个。

对象可以被创建和销毁,但类是无所不在的。

(1)定义对象:

属于不同的类的对象在不同的时刻,不同的地方分别被建立。全局对象在主函数开始执行前首先被建立,局部对象在程序执行到他们的对象定义时才被建立。与定义变量类似,定义对象时,C++为其分配空间。

(2)对象的初始化:

根据变量的定义,全局变量和静态变量在定义(分配内存空间)时,将位模式清零,局部变量在定义时,分配的内存空间内容保持原样,故为随机数。

对象定义时,情况不一样。对象的意义表达了现实世界的实体,因此,一旦建立对象,须有一个有意义的初始值。C++建立和初始化对象的过程专门有该类的构造函数来完成。这个构造函数很特殊,只要对象建立,它马上被调用,给对象分配空间和初始化。例如一旦打造了一张桌子,桌子就应该有长宽高。 因此,在桌子对象建立时,构造函数的任务是赋予一组值给该桌子对象。如果一个类没有专门定义构造函数,那么C++就仅仅创建对象而不作任何初始化。

2、构造函数的需要性:

变量初始化的方法如下所示:

int a=1; int * pa=&a;

但是对类对象来说,如此初始化不行,这是由类的特殊性所决定的。(其中拥有私有的成员)

类的封装性,就体现在一部分数据是不能让外界访问的。所以直接在非成员函数中访问类对象的保护或私有数据是不允许的。

类对象的初始化任务,就落在了类的成员函数身上,因为他们可以访问保护和私有数据成员。于是将初始化构想成下面的形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<iostream>
#include<string>
usingnamespacestd;
#ifndef STUDENT_H
#define STUDENT_H
classStudent
{
public:
Student();
intaddcoures(intsh,ints)
{
somehours = sh; score = s;
return0;
}
~Student();
private:
intsomehours;
float score;
};
Student::Student()
{
}
Student::~Student()
{
}
#endif

类的保护数据在外界是不能访问的,所以对这些数据的维护是类的分内的工作。将初始化工作交给addcoures()成员函数无可非议,但却让系统多了一道处理初始化的解释与执行,因为他意味着在编写应用程序中每当建立对象时,都要人为的增加书写代码。这样实现的类机制,并不理想。

所以,我们要求在建立对象的同时,自动调用构造函数,省去认为调用的麻烦,也就是说,类对象的定义:student ss;

明确表达了为对象分配空间和初始化的意向。这些工作由构造函数来完成。

类对象定义了student ss;涉及到一个类名和一个对象名。类只有一个名字,但对象名可以任意多,每个对象创建时,每个对象都要调用该类的构造函数,类的唯一性和对象的多样性,使我们马上想到用类名而不是对象名来作为构造函数名是比较合适的。

3、构造函数的使用:

C++规定与类同名的成员函数是构造函数,在该类的对象创建时,自动被调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
classStudent
{
public:
Student()
{
somehours =0; score =0;
}
intaddcoures(intsh,ints)
{
somehours = sh; score = s;
return0;
}
~Student();
private:
intsomehours;
float score;
};

构造函数可以放在类的外部定义:

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
classStudent
{
public:
Student();
intaddcoures(intsh,ints)
{
somehours = sh; score = s;
return0;
}
~Student();
private:
intsomehours;
float score;
};
Student::Student()
{
}
Student::Student()
{
somehours =0; score =0;
}
Student::~Student()
{
}

放在外部定义的构造函数,其函数名之前要加上类名::,这个别的成员函数的定义一样。因为在类定义的外部,可能有各种函数定义,为了区分成员与非成员函数,区分此类成员函数和彼类成员函数,所以加上类名::是必要的。

构造函数另一个特殊之处是他们没有返回类型,函数体中也不允许返回值,但可以有无值返回语句return。

如果一个类对象是另一个类的数据成员,则在那个类的对象创建所调用的构造函数中,对该成员(对象)自动调用其构造函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<iostream>
#include<string>
#include"teacher.h"
#include"xuesheng.h"
usingnamespacestd;
#ifndef TUTOPAIR_H
#define TUTOPAIR_H
classTutopair
{
public:
Tutopair();
~Tutopair();
private:
Teacher tea;
Xuesheng stu;
intcnt;//会晤次数
};
Tutopair::Tutopair()
{
cout <<"tutopair"<< endl;
cnt =0;
}
Tutopair::~Tutopair()
{
}
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
#include<string>
usingnamespacestd;
#ifndef TEACHER_H
#define TEACHER_H
classTeacher
{
public:
Teacher();
~Teacher();
private:
};
Teacher::Teacher()
{
cout <<"teacher "<< endl;
}
Teacher::~Teacher()
{
}
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<iostream>
#include<string>
usingnamespacestd;
#ifndef XUESHENG_H
#define XUESHENG_H
classXuesheng
{
public:
Xuesheng();
~Xuesheng();
private:
intsomehours;
intscore;
};
Xuesheng::Xuesheng()
{
cout <<"xuesheng"<< endl;
somehours =100;
score =90;
}
Xuesheng::~Xuesheng()
{
}
#endif
1
2
3
4
5
6
7
8
9
10
11
#include"teacher.h"
#include"Tutopair.h"
#include"xuesheng.h"
#include<iostream>
usingnamespacestd;
intmain()
{
Tutopair tp;
system("pause");
return0;
}

这个例子,告诉我们。类在工作过程中,分工十分明确,每个类只负责初始化自己的对象。当totupair类要初始化成员xuesheng类对象的时候,马上调用学生构造函数,而不是由自己去包办。正所谓”你做你的事,我做我的事情。“

4、析构函数。

一个类可能在构造函数里分配资源,这些资源需要在对象不复存在以前被释放。例如,如果一个构造函数打开了一个文件,文件就需要被关闭。或者,如果构造函数从堆中分配了内存,这块内存在对象消失之前必须被释放。析构函数允许自动完成这些清理工作,不必调用其他成员函数。堆对象析构。

析构函数也是特殊的类成员函数,他没有返回类型,没有参数,不能随意调用,也没有重载。只是在类对象生命周期结束的时候,由系统自动调用。构造函数可以不同于析构函数,却可以有参数,可以重载。

作为一个类,可能有许多对象,每当对象生命周期结束时,都要调用析构函数,每个对象一次。这跟构造函数鲜明对立,所以析构函数名就在构造函数名前加上~。标识“逆结构函数”。

当你进入图书馆时,你就成了一个阅览人(对象),借什么书是由一进去就完成的(构造)。当你要撤离阅览室时(撤销对象),你必须先归还书本(析构)才能离去。

析构函数以调用构造函数相反的顺序被调用。

5、带参数的构造函数。

前面介绍的构造函数不能完全满足初始化的要求。因该让构造函数可以带参数,否则:往往程序员只能向将对象构造成千篇一律的对象值,甚至一个随机值对象,然后再调用一个初始化成员函数将数据存到该对象中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include<iostream>
#include<string>
usingnamespacestd;
#ifndef XUESHENG_H
#define XUESHENG_H
classXuesheng
{
public:
Xuesheng(char* pname);
~Xuesheng();
private:
intsomehours;
intscore;
char name[21];
};
Xuesheng::Xuesheng(char * pname)
{
cout <<"construct xuesheng"<< pname << endl;
strncpy(pname, name, sizeof(name));
name[sizeof(name)-1] ='

免责声明:内容来源于网络,仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇xxl-job编写GULE(Java)运行模式,带执行参数(url)vue项目中引入 html2canvas ,控制台报错 Cannot assign to read only property 'className' of object '#&amp;lt; SVGSVGElement &amp;gt;'下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

QT父子窗口事件传递与事件过滤器(讲了一些原理,比较清楚)

处理监控系统的时候遇到问题,在MainWidget中创建多个子Widget的时候,原意是想鼠标点击先让MainWidget截获处理后再分派给子Widget去处理,但调试后发现如果子Widget重新实现了事件方法,就直接处理掉事件了,没有进到MainWidget的处理方法中去,如果子Widget没有accept或ignore该事件,则该事件就会被传递给其父亲...

CS231N 数据预处理(data proprecessing)

原文链接:https://blog.csdn.net/weixin_38646522/article/details/79534677 一些数据预处理的标准方法有均值化数据和归一化数据。 零中心化的意义在上面已经详细的讲述了,这里就不在细讲。 归一化数据的意义在于让所有的特征都在相同的值域之内,并且让这些特征有相同的贡献。对于图像处理,在大部分情况下会进...

Ogre 渲染队列(二)

转自:http://www.cnblogs.com/cppguru/archive/2009/11/25/1610626.html 简要说Ogre渲染主流程分三步使用渲染队列:清空、构造和访问,这个过程在每一帧的绘制过程中重复执行。 渲染队列的清空 Ogre在每一帧渲染前都会先清空渲染队列。熟悉Ogre渲染流程的很容易看到在SceneManager::_r...

python魔法方法、构造函数、序列与映射、迭代器、生成器

在Python中,所有以__双下划线包起来的方法,都统称为"魔术方法"。比如我们接触最多的__init__,魔法方法也就是具有特殊功能的方法。 构造函数 构造函数不同于普通方法,将在对象创建后自动调用它们。也就是在对象创建完成后,自动会调用__init__方法来初始化。 创建一个构造方法 构造方法传参 >>> classFooBar...

Windows消息机制详解

消息是指什么? 消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉。一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向 Windows发出一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。 消息本身是作为一个记录传递给应用程序的,这个记录中包含...

php性能调优

第一章  针对系统调用过多的优化 我这次的优化针对syscall调用过多的问题,所以使用strace跟踪apache进行分析。 1.  apache2ctl -X & 使用-X(debug)参数启动httpd进程,这个时候只启动1个httpd进程 2. ps -ef | grep httpd 找到需要strace的pid 3. strace -p...