一.类
1.概念:类是对具有相同属性和行为的一组对象的抽象与统一描述。是用户自定义的数据类型
(属性以数据表示,行为通过函数实现)
C++中,类的名字就是用户自定义的类型的名字。可以象使用基本类型那样来使用它
2.格式:
class 类名——类名的首字母大写
{
public:
公有数据成员和成员函数;
protected:
保护数据成员和成员函数;
private:
私有数据成员和成员函数;
};(类的定义以分号结束,不可省略)
注:(1 .数据成员私有化——只在类中可见
成员函数公有化——类中,类外均可见
(2.如果私有成员放在第一段,则可以省略关键字private
(3.类的任何成员都必须指定访问属性
类的访问属性有:
Public
Protected
Private
(4.类的成员可以是其他类的对象(称为类的组合),但不能以类自身的对象作为本类的成员,而类自身的指针和引用可以作为类的成员。
(5.在类的定义中不能对数据成员进行初始化
(6.类中的数据成员可以是C++语法规定的任意数据类型
3.成员函数
一般将成员函数声明为函数原型,在类外具体实现成员函数。
类外定义格式:返回值类型 类名::成员函数名(参数表)
{
函数体
}
简单成员函数可以在类中定义
成员函数重点是对数据成员做操作
二.对象
对象是类的实例或实体。类与对象的关系,如同C++基本数据类型和该类型的变量之间的关系。
格式:类名 对象名1,对象名2,…,对象名n;
注:(1.必须在定义了类之后,才可以定义类的对象。
(2.对象必须定义在主函数中
1. 对象成员的访问包括:
圆点访问形式:对象名.公有成员
指针访问形式:对象指针变量名->公有成员
例:
#include<iostream>
using namespace std;
class Tclass
{public:
int x,y;
void print()
{cout<<x<<","<<y<<endl;}
};
int add(Tclass *ptf)
{return(ptf->x+ptf->y);}
int main()
{Tclass test,*pt=&test;
pt->x=100;
pt->y=200;
pt->print();
test.x=150;
test.y=450;
test.print();
cout<<"x+y="<<add(&test)<<endl;
}
三.内联函数:即成员函数在类内实现。编译器在编译时,将内联函数的调用以相应代码代替
声明:inline 函数原型
注:内联函数仅在函数原型作一次声明。
适用于只有1 ~ 5行的小函数
不能含有复杂结构控制语句 ,不能递归调用
四.函数重载:函数名相同,但参数不相同(类型不同,或者个数不同)的一组函数。
用于处理不同数据类型的类似任务
五.构造函数和析构函数
| 构造函数 | 析构函数 |
定义 | 构造函数是用于创建对象的特殊成员函数。 当创建对象时,系统自动调用构造函数
| 析构函数是用于取消对象的特殊成员函数。 当一个对象作用域结束时,系统自动调用析构函数
|
格式 | 类名::类名(参数表) | 类名::~类名() |
| 没有用户定义的构造函数时,系统提供缺省版本的构造函数
| 没有用户定义析构函数时,系统提供缺省版本的析构函数
|
| 可以有任意类型的参数 但没有返回类型 构造函数可以重载 | 没有参数 也没有返回类型 也不能重载
|
作用 | 为对象分配空间; 对数据成员赋初值 请求其他资源个
| 进行对象消亡时的清理工作 比如:释放成员(指针)所占有的存储空间 |
| 一个类中可以有多个构造函数 | 一个类中只能有一个析构函数 |
默认**函数 | 默认构造函数如果类中没有定义构造函数,系统将自动生成一个默认形式的构造函数,用于创建对象。 格式:类名::类名(){}——是一个空函数
| 默认析构函数若没有显式定义析构函数,则系统自动生成一个默认形式的析构函数。 格式:类名::~类名(){}
|
1.构造函数:
构造函数名与类名相同
构造函数需定义两个以上。一个带参的,跟着一个不带参的
构造函数只在创建对象是调用一次
—(1)—利用构造函数创建对象的两种方法
1 利用构造函数直接创建对象.其一般形式为:
类名 对象名[(实参表)];
这里的“类名”与构造函数名相同,“实参表”是为构造函数提供的实际参数。
2利用构造函数创建对象时,通过指针和new来实现。其一般语法形式为:
类名 *指针变量 = new 类名[(实参表)];
例如:
Date *date1=new Date(1998,4,28);
就创建了对象(*date1)。
—(2)—构造函数初始化成员有两种方法
1.使用构造函数的函数体进行初始化
class Date
{
int d, m, y;
public:
Date(int dd, int mm, int yy)
{
d=dd;
m=mm;
y=yy;
}
Date(int dd, int mm)
{
d=dd;
m=mm;
}
}
Date(intdd, int mm) { d=dd; m=mm; }}
2.使用构造函数的初始化列表进行初始化
格式:
funname(参数列表):成员名1(形参名1),成员名2(形参名2),成员名n(形参名n)
初始化列表
{ 函数体,可以是空函数体 }
class Date
{
int d,m, y;
public:
Date(intdd, int mm, int yy):d(dd),m(mm),y(yy)
{ }
Date(intdd, int mm): d(dd),m(mm)
{ }
}
—(3)—必须使用参数初始化列表对数据成员进行初始化的几种情况
- 数据成员为常量
- 数据成员为引用类型
- 数据成员为没有无参构造函数的类的对象
—(4)—类成员的初始化的顺序
按照数据成员在类中的声明顺序进行初始化,与初始化成员列表中出现的顺序无关
—(5)—构造函数的重载
class Box{
public:
Box();
Box(int,int , int);
intvolume();
private:
intheight,width, length;
};
Box::Box()
{ height=10; width=10; length=10;}
Box::Box(int h, int w,intl):height(h),width(w),length(l)
{}
int Box::volume()
{ returnwidth*length*height;}
int main(){
Boxbox1;
cout<<"Thevolume is "<<box1.volume();
Boxbox2(12,30,25);
cout<<"Thevolume is "<<box2.volume();
return0;
}
—(6)—带默认值的构造函数
#include<iostream>
usingnamespace std;
class Box
{
public:
Box(); //定义了全部带默认值的构造函数,不能再定义无参构造函数
Box(int h=10,int w=10 , int l=10); //只能在声明时指定默认值
int volume();
private:
int height,width, length;
};
—(7)—构造函数的调用
在生成对象时调用构造函数。(构造函数一般被定义为公有成员)
classPerson
{
public:
void setAge( unsigned n ){ age = n; }
unsigned getAge( ) { return age; }
private:
unsigned age;
};
intmain()
{
person a;
person b[60]
…….
2.析构函数
一般情况下,可以不定义析构函数
但如果类的数据成员中包含指针变量是从堆上进行存储空间分配的话,需要在析构函数中进行存储空间的回收
六.this指针
为使类的成员函数区分不同的实例对象的数据成员,C++专门设立了一个名为this的指针,用来指向不同的对象。
一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果
1. 需要显式引用this指针的三种情况
(1)在类的非静态成员函数中返回类对象本身或对象的引用的时候,直接使用 return *this,返回本对象的地址时,return this。
(2)当参数与成员变量名相同时,如this->x = x,不能写成x = x。
(3)避免对同一对象进行赋值操作,判断两个对象是否相同时,使用this指针。
七.复制构造函数
复制构造函数用一个已有同类对象创建新对象进行数据初始化
格式: 类名 :: 类名(const 类名 & 引用名 , …);
1. 特点:
(1) 复制构造函数名与类名相同,并且也没有返回值类型。
(2) 复制构造函数可写在类中,也可以写在类外。
(3) 复制构造函数要求有一个类类型的引用参数。
(4) 如果没有显式定义复制构造函数,系统自动生成一个默认形式的复制构造函数。
2. 复制构造函数的调用
以下三种情况下由编译系统自动调用:
(1)声明语句中用类的一个已知对象初始化该类的另一个对象时。
(2) 当对象作为一个函数实参传递给函数的形参时,需要将实参对象去初始化形参对象时,需要调用复制构造函数。
(3) 当对象是函数的返回值时,由于需要生成一个临时对象作为函数返回结果,系统需要将临时对象的值初始化另一个对象,需要调用复制构造函数。
八.浅复制与深复制
1.浅复制:
在用一个对象初始化另一个对象时,只复制了数据成员,而没有复制资源,使两个对象同时指向了同一资源的复制方式称为浅复制。
即:对于复杂类型的数据成员只复制了存储地址而没有复制存储内容
2.深复制:
通过一个对象初始化另一个对象时,不仅复制了数据成员,也复制了资源的复制方式称为深复制。
(1)深复制构造函数必须显式定义
(2)格式:类名::类名([const] 类名 &对象名);
九.类的其他成员
1.常成员
常数据成员是指数据成员在实例化被初始化后,其值不能改变。
使用const说明的数据成员称为常数据成员。const int M;
——常对象
如果在说明对象时用const修饰,则被说明的对象为常对象。
格式:类名 const 对象名[(参数表)];
或 const 类名对象名[(参数表)];
注:(1)C++不允许直接或间接更改常对象的数据成员。
(2)C++规定常对象只能调用它的常成员函数、静态成员函数、构造函数(具有公有访问权限)。
—— 常成员函数
在类的成员函数说明后面可以加const关键字,则该成员函数成为常量成员函数
格式: 类型说明符函数名(参数表) const;
注: 常成员函数不能更新对象的数据,也不能调用非const修饰的成员函数(静态成员函数、构造函数除外)
2.静态成员
类成员冠以static声明时,称为静态成员。
class A
{
int n;
staticint s;
};
在类外进行静态数据成员的声明
格式:类型类名::静态数据成员[=初始化值];
| 静态成员 | 静态成员函数 |
定义格式 | Static 类型名 静态成员名 | static 返回类型 静态成员函数名(参数表);
|
访问格式 | 公有访问权限的静态成员 | 调用公有静态成员函数 |
类名::静态成员的名字 对象名.静态成员名字 对象指针->静态成员的名字
| 类名::静态成员函数名(实参表) 对象. 静态成员函数名(实参表) 对象指针->静态成员函数名(实参表) 在静态成员函数内部,直接访问 | |
|
|
|
3. 友元
在类体中用friend对其(函数B)进行声明,此函数就称为本类(类A)的友元函数
注:1.友元函数(函数B)可以访问这个类(类A)中的私有成员
2.这个函数可以是不属于任何类的非成员函数,也可以是其他类的成员函数
#include <iostream>
using namespace std;
class Car;
class Boat{
intweight;
public:
Boat(intw):weight(w){}
friendvoid display_weight(Boat &boat ,Car &car);
};
十.类的包含(类的组合)
当一个类中含有已经定义的类类型成员,带参数的构造函数对数据成员初始化,须使用初始化语法形式
格式:构造函数( 形参表) : 对象成员1(形参表) , … , 对象成员n (形参表) ;
十一.对象数组
所谓对象数组是指每一数组元素都是对象的数组。
格式 :类名数组名[下标表达式];
对象数组的初始化(无法通过初始化成员列表对对象数组进行初始化)
1. 当对象数组所属的类中包含带参的构造函数,可用初始化列表完成对象数组的初始化2. 当对象数组所属的类中包含无参的构造函数,也可以先定义,再给每个数组元素赋值
3. 当对象数组所属的类中包含单个参数的构造函数,可简写