类和对象
(
一
)
前言:类(
class
)是
C++
的精华,是
C++
最重要的特征,是进行封装和数据隐藏的工具。类对象是类的实例。
1.
结构
C
语言中:结构是一种自定义的数据类型,在结构体中可以含有各种不同类型的数据。
C++
中:对结构类型进行扩充,它不仅可以含有不同类型的数据,而且还可以含有函数。
结构的成员(包括数据和函数)
①私有成员(private):只能被该结构中的其它成员访问
②公有成员(public):既可被结构内其他成员访问,也可被结构外的其它部分访问。
注意:C++规定,在缺省情况下,结构中的成员是公有的。
2.
类的声明
类是
C++
的一个最重的特性,是比结构类型更安全有效的数据类型。其一般形式如下:
class
类名
{
[private: ]
私有数据成员和成员函数
;
public:
公有数据成员和成员函数
;
private:
保护数据成员和成员函数
;
}
;
其中:
class
是声明类的关键字,类名是要表明的类的名字,后面的花括号表示出类的声明范围;最后分号表示类声明结束。
类的成员:①私有成员:被该类的成员函数访问
②公有成员可被程序中的其它函数访问,是类的对外接口。
③
保护成员在类中等同于私有成员,在继承中等同于公有成员。
注意:C++规定,在缺省情况下,类中的成员是
私有
的。
类的作用域:指在类的声明中的一对花括号所形成的作用域。
说明:
(1)
数据成员可以是任何数据类型,但不能用自动(
auto
)寄存器
(vegister)
或外部
(extern)
进行说明。
(2)
不能在类的声明中给数据成员赋初值。只有在类对象定义后才能给数据成员赋值。
(3)
成员函数,又称方法。其定义通常采取两种方式:外部定义,内部定义
(
①隐式定义:直接将函数定义在类内部
;
②显式定义:在类定义体外定义内置函数,在函数定义前冠以“
inline
”
)
。
3.
对象的定义及引用
对象的定义的两种定义:
1.
在声明类的对象时,直接定义对象,即在声明类的右花括号“
}
”后,直接写出该类的对象名表。
2.
声明了类之后,在使用时,再定义。
对象的引用的含义:指对对象成员的引用。
格式:
对象名
.
数据成员名
或对象名
.
成员函数名(实参表)
4.
构造函数与析构函数
引言:当声明一个类对象时,编译程序需要为对象分配存储空间,进行必要的初始化。在
C++
中,由构造函数来完成这些工作。与构造函数对应的是析构函数,当撤消类对象时,析构函数就回收存储空间,并做一些善后工作。构造函数、析构函数是属于某一个类的,可以由用户提供,也可由系统自动生成。
4.1
构造函数
(1)
定义:是一种特殊的成员函数。
(2)
一般定义格式:类名::构造函数名(参数表)
{
构造函数体;
}
(3)
一般使用格式:类名
对象名(参数表);
(4)
作用:为对象分配空间,进行初始化。
(5)
性质:
①构造函数名字必须与类名相同
②构造函数可以有任意类型的参数,但不能具有返回类型
③定义对象时,编译系统会自动调用构造函数
4.2
构造函数的初始化
④构造函数可以是不带参数的,但不带参数的构造函数对对象的初始化是固定的。
⑤构造函数也可采用构造初始化表对数据成员进行初始化,若需要将数据成员存放在堆中或数组中,则应在构造函数中使用赋值语句。
⑥没有定义构造函数的类,其公有数据成员可以用初始值进行初始化。
4.3
其他构造函数
1.缺省参数的构造函数:在实际使用中,有些构造函数的参数值通常是不变的。在特殊情况下需要改变它的参数值时,可将其定义成带缺省参数的构造函数,如:
2.重载构造函数:C++允许重载构造函数,此适应不同的场合。
3.拷贝构造函数:是一种特殊的构造函数,用于依据已存在的对象建立一个新对象。
4.4
析构函数
引言:析构函数 是一种特殊的成员函数。用于执行一些清理任务。
⑴格式:类名::~类名
(参数表)
{
构造函数体;
}
⑵特点:①析构函数名必须与构造函数名,在它前面必须加一个波浪号“~”。
②析构函数没有参数,没有返回值,而且不能重载。
5
.静态成员
静态成员的提出是为了解决数据共享的问题。在类中,静态成员分为静态数据成员和静态成员函数。在声明一个静态成员时,前面须加上
static
修饰。
<1>
静态数据成员
静态数据成员是类的所有对象共享的成员,只储存在一处,供所有对象公用。静态数据成员的值对每个对象都是一样的,但它的值是可以更新的。
静态数据成员的使用方法和注意事项如下:
·静态数据成员在定义时或说明时前面加关键字
static.
·静态数据成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式如下:
<
数据类型
><
类名
>::<
静态数据成员名
>=<
值
>;
·静态数据成员必须进行初始化。
·引用静态数据成员时,采用如下格式:
<
类名
>::<
静态数据成员
>;
<2>
静态成员函数
静态成员函数和静态数据成员一样,它们都属于类的静态成员,它们都不是对象成员。因此,对静态成员的引用不需要用对象名。在静态成员函数的实现中不能直接引用类中说明的静态成员,可通过对象来引用。
调用静态成员函数使用如下格式:
<
类名
>::<
静态成员函数
>(<
参数表
>)
或对象
.
静态成员函数
(<
参数表
>)
说明
:
<1>
静态成员函数可以定义成内嵌的,也可以在类外定义,在类外定义时,不要用
static
前缀;
<2>
静态成员函数一般地说访问的是静态数据成员,特殊情况下可用非静态成员。
<3>
静态成员函数和一般成员函数的唯一区别是没有隐含的指针;如果要在函数中访问某个特定对象的成员,必须结合使用操作符“·”或“
-
〉”来显式地指定所属对象。
6.
友元
通过成员函数频繁地访问私有数据,大有不便;友元就对访问私有数据开了“后门”。
6.1
友元函数
:
友元函数不是当前类的成员函数,而是独立于当前类的外部函数,但它可以访问该类所有对象的成员,包括私有成员和公有成员。
其类内格式如下:
friend<
类型
><
友元函数名
>(<
参数表
>);
6.2
友元成员
:
除了一般的函数可以作为某个类的成员外,一个类的成员函数也可以作为另一个类的友元,这种成员函数不仅可以访问自己所在类对象中的私有成员和公有成员,还可以访问
friend
申明语句所在类对象中的私有成员和公有成员,这样能使两个类相互合作、协调工作,完成某一任务。
6.3
友元类
:
不仅函数可以作为一个类的友元,一个类也可以作为另一个类的友元。这种友元类的说明方法是在另一个类申明中加入语句“
friend
类名(即友元类的类名);”。
7.
类对象
7.1
对象数组
:
每一数组元素都是对象的数组。初始化方法:通过初始化表或构造函数。
7.2
对象指针
:
指针引用单个对象,指针引用对象数组
7.3 this
指针
:
是成员函数所属对象的指针。当调用成员函数时,它被初始化为被调用函数所在的类实例对象的地址。
This
指针幕后工作方式,如存在
student
类:
student obj
;
obj.load(100); / /
等价与
load(&obj,100)
相应的类中的形式为
void load (exth *this,int val) {this->i=val;}
7.4
对象参数
:
分为对象传值和对象传地址两种方式。
7.5
对象成员
:
在类定义中的数据成员一般都是基本的数据类型。但是类中的成员也可以是对象,叫做对象成员。使用对象成员着重要注意的问题是构造函数的定义方式,即类内部对象的初始化问题。此外,当调用类构造函数首先按各对象成员在类定义中的顺序依次调用它们的构造函数,对这些对象初始化,最后执行类构造函数体。析构函数的调用顺序与此相反。
7.6
临时对象
:
student fn()
{ //
…
..
student ms(
“
randy
”
);
return ms;
}
void main()
{ student s;
s=fn();
//…………….
student & ref=fn();
}
过程:函数
fn
栈区→临时变量→函数
main
栈区,其中
ms
为临时对象。
7.7
无名对象
:
如果对象
s
仅仅是为了充当
fn
()的实参,可以采用无名对象。
student(
“
Randy
”
);
void fn(student s);
fn(student(
“
Randy
”
));//
等价与
student s(
“
Randy
”
); fn(s);
8. const
成员函数
:
1.
类方法声明为
const
的条件
:
该方法一定不能改变该类的任何一个数据成员的值
.
2.
格式
返回类型
成员函数名
(
参数表
) const;
称为常量成员函数或常量函数
3.
若声明了一个指向
const
型对象的指针
,
那么该指针只能调用
const
方法
,
即常量函数
4.
对于不改变对象的成员函数都要将其声明为
const,
以便于编译器查错
5.
传值形参
:
被复制到栈
,
费时
,
占用内存
,
增加开销
(
例如传递对象
,
先调用拷贝构造函数
;
当函数返回时
,
调用析构函数
).
6.
地址形参
:
效率高
,
但危险
,
形参随时处于被修改的境地
.
7.
解决方法
:
传递
const
地址形参
,
即
const
引用形参
, const
指针形参。