C++类

一:面向对象程序设计的基本概念:
面向对象程序设计简称OOP;面向对象程序设计涉及的基本概念包括:类与对象,抽象与封装,继承与多态;

1.类与对象
1.1-对象是具有某种特性和某种功能的东西,自然界中的任何事物都可以称为对象。对象是由一组数据和施加在这些数据上的一组操作构成的。对象的基本特性:a.有一个状态;b.有一个名字以区别于其他对象;c.有一系列的操作,而每一个操作决定对象的一种行为;d.对象的状态只能被自身的行为所改变;e.对象之间通过消息进行传讯;f.一个对象的状态可由其他的对象的状态构成;
1.2-对象抽离了自然存在的实体,描述了实体的结构特征和行为特征。如果一个对象的状态由其他对象表示,就称构成他的状态的对象是它的属性;对象的结构特性由它的属性表示,对象的每一个操作称为方法,一个对象的方法是其对其他对象的可见的接口;一个对象向另一个对象发送消息,以激活他的某个方法,对象的每个方法对应且仅对应一条消息;
1.3-在面向对象程序设计中,将同一种类型的对象归属为一个类,以类的形式描述对象的状态和功能,任何对象都属于某个类;事实上,是一组具有相同结构特征和行为特征的对象构成了一个类,而所有这些对象都是类的一个实例;1.4-一个类的不同实例具有以下特征:
a.相同的方法集合;
b.相同的属性定义,但可以有不同的属性值;
c.对象名称不同;
?1.5-子类:
一个类A是另一个类B的子类,必须具有:
a.类B的所有属性定义包含在类A中;
b.类B的所有方法定义包含在类A中;
c.类A中可以包含类B中没有的属性和方法;

2.抽象与封装
类是面向对象程序设计的根本,类的特性是抽象和封装;
2.1-抽象是科学研究中经常使用的方法。所谓抽象就是对研究对象的人为处理,它忽略研究对象非本质的次要部分,抽取人们关心的核心部分加以研究和描述;为对象建立类这是面向对象程序设计的基础与核心。类就是抽象数据模型,用它描述对象;
2.2-通过类将对象的特性和功能组合成一个整体,称为封装。构造类是建立封装的实体,类作为一个整体使用,内部构造被隐藏起来;

3.继承
继承是面向对象程序设计的一大特点。在原有类的基础上,经过适当的扩充和完善派生出的新类,称之为子类或派生类,原有的类称为子类的父类或基类,也可称为超类;子类和父类形成类的层次和类的继承;由于子类是在父类的基础上建立的,因此子类继承了父类的特性和功能。通过类的继承机制可以实现程序代码的重用,提高程序设计效率;

4.多态
多态是与继承相关的另一个重要概念。通过多态,对象能够根据收到的参数产生相应的操作,即每个对象能够以适应自己的形式完成操作。通过多态使对象具有应变能力,适应各种需要,多态提高了已有代码的可扩容性;

二:C++类的定义和使用
1.类的定义:
class 类名
{private:
数据类型 变量名1;//定义数据成员(变量),用于存储数据
数据类型 变量名2;

数据类型 变量名n;
public:
返回值类型 函数名1([形式参数列表])//定义函数(方法),实现类的功能
{若干语句}
返回值类型 函数名2([形式参数列表])
{若干语句}

返回值类型 函数名n([形式参数列表])
{若干语句}
};

(1)[]中的内容是可选项,根据需要选择或省略;
(2)class是C++的关键字,用class表明定义类;
(3)public和private是访问控制说明符,用于说明类中标识符的作用域。关键字public以后声明的标识符为公有标识符,这些标识符对外公开,可在类外使用。关键字private以后声明的标识符是私有标识符,这些标识符不对外公开,只能在该类中使用。
(4)类名是标识符,在为类取名时要符合C++对标识符的规定,一般类名首字母为大写;
(5)可以先定义类的数据成员,也可以先定义类的成员函数。定义顺序对类没有影响;
(6)类的成员函数可以在类中定义,也可以在类外定义,在类外定义的格式为:
class 类名
{private:
数据类型 变量名1;//定义数据成员(变量),用于存储数据
数据类型 变量名2;

数据类型 变量名n;
public:
返回值类型 函数名1([形式参数列表])//定义函数(方法),实现类的功能
{若干语句}
返回值类型 函数名2([形式参数列表])
{若干语句}

返回值类型 函数名n([形式参数列表])
{若干语句}
};
类名::函数名1([形式参数列表])//在成员函数名前加上类名和分隔符“::”
{若干语句}
类名::函数名2(【形式参数列表】)
{若干语句}

类名::函数名n(【形式参数列表】)
{若干语句}

2.对象与类的使用:
定义类是为了使用类,一般来说通过类对象使用类,也就是说,首先要为类创建对象,然后才能使用类。类只是抽象的数据模型,类对象才是具体的,可操作的实体。利用类对象使用类提供的功能;

2.1-创建对象:
类名 对象名;
a.一旦创建了对象,对象就拥有自己的内存空间,用于存储该对象的所有信息,即存储他的数据成员和成员函数。以后对象的一切操作都在这块内存空间中进行。这正是对象封装特性的体现;
b.可以为一个类建立多个对象,每个对象占用不同的内存空间,相互独立,互不影响;
2.2-调用成员函数:
也称引用成员函数或使用成员函数,格式为:
对象名.函数([实际参数列表])
a.调用成员函数中的.是引用运算符,表示需要使用对象中的函数;
b.使用有形参的成员函数,需用实参替换函数中的形参,使用无参成员函数时,不需要实参,但圆括号不能省略;

三:类的成员函数
1.构造函数与析构函数:
(1)构造函数是类的特殊函数,用于初始化新建对象,即将初始值赋予对象的数据成员,构造函数与类同名,当创建新对象时,自动调用构造函数为对象初始化,如果类中没有定义构造函数,系统会提供一个默认的构造函数,既无参数也无任何操作;
(2)析构函数也是类的特殊函数,用于删除对象,与类同名,但在函数名前加上标识符~。一个类中只能有一个析构函数,系统会提供一个默认的析构函数,当对象不在他的有效范围内时,系统会自动调用析构函数,删除该对象;
例:
class cube
{public:
cube(int ht,int wd,int dp);//构造函数
~cube();//析构函数
int volume();//成员函数,用于计算立方体的体积
private:
int height,width,depth;//私有数据成员
};
cube::cube(int ht,int wd,int dp)//构造函数内容
{
height=ht;width=wd;depth=dp;
cout<<“Constructor called”<<endl;
}
cube::~cube()//析构函数内容
{
cout<<“Destructor called”<<endl;
}
int cube::volume()
{
return heightwidthdepth;
}
void main()
{
cube cubeone(10,20,30);//创建一个cube类对象,自动调用构造函数
cout<<cubeone.volume()<<endl;
}

a.程序首先执行构造函数,然后执行cubeone.volume()函数,最后执行析构函数,删除对象,程序结束;
b.在程序中不能直接调用构造函数和析构函数。只有建议对象时,才调用构造函数,当函数程序运行结束前,调用析构函数,删除对象;
2.进一步讨论构造函数:
(1)可以为一个类定义多个构造函数。定义多个构造函数称为构造函数重载。各个构造函数具有相同的名字,但参数的有无,参数类型和个数等可以不同。
(2)构造函数可以有缺省值。当创建对象没有指定初始值时,则使用缺省值作为初始值;
(3)拷贝构造函数也是一个构造函数,他的特殊功能在于将参数代表的对象逐一拷贝到新创建的对象,拷贝构造函数有两种形式:
a.系统自动产生。当类中没有建立拷贝构造函数时,系统将为类自动建立一个缺省的拷贝构造函数;
b.用户自定义。如果类中已经定义了拷贝构造函数,那么在创建对象时不在调用缺省的拷贝构造函数,而是调用用户自定义的拷贝构造函数;
cube cubeone(10,20,30);//定义cube类的对象cubeone
cube cubetwo(cubeone);//定义cube类的对象cubetwo,调用系统默认的拷贝构造函数
当创建对象cubeone时,系统调用带参数的构造函数,在创建对象cubetwo时,调用系统自动为类建立的拷贝构造函数,该构造函数仅将对象cubeone各变量的值拷贝给对象cubetwo,没有其他操作;
cube(cube&p)//自定义拷贝构造函数
{height=p.height;width=p.width;depth=p.depth;
cout<<“Destructor3 called”<<endl;
}

void main()
{cube cubeone(10,20,30);
cube cubetwo(cubeone);
cout<<cubeone.volume()<<endl;//输出6000
cout<<cubetwo.volume()<<endl;//输出6000
}
当创建对象cubetwo时系统不再调用缺省的拷贝构造函数,而是调用类中自定义的拷贝构造函数;

3.在线函数(inline)
用关键词inline修饰的函数称为在线函数或内联扩展函数。当一个inline函数在主程序中被多次调用时,其源代码被复制到调用处,对于频繁调用的函数来说,运用这一特性可以避免调用函数带来的开销,提高程序的运行速度,也可以将类的成员函数定义为inline函数;
例:
#include <iostream.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system(“pause”) or input loop */
inline void voutput()
{
cout<<“This is inline function!”<<endl;
}
int main()
{
int t;
cout<<“program to print a massage sevesal times.”<<endl;
for(t=0;t<3;t++)
voutput();
return 0;
}


program to print a massage sevesal times.
This is inline function!
This is inline function!
This is inline function!


Process exited after 0.141 seconds with return value 0
请按任意键继续. . .

例:inline成员函数举例
#include <iostream.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system(“pause”) or input loop /
class cube
{public:
cube(int ht,int wd, int dp)
{height=ht;
width=wd;
depth=dp;
cout<<“Constructor called”<<endl;
}
~cube()
{
cout<<“Destructor called”<<endl;
}
inline int volume()
{
return height
width*depth;
}
private:int height,width,depth;
};
int main()
{
cube cubeone(10,20,30);
cout<<cubeone.volume()<<endl;
return 0;
}


Constructor called
6000
Destructor called


Process exited after 0.1349 seconds with return value 0
请按任意键继续. . .

类的每项操作都由成员函数来实现,使用某个函数需要调用某个成员函数,开销很大,在线函数将函数的代码插入到函数的每个调用处,减少了调用函数带来的开销,但增加了程序代码的长度;如果对在线函数定义作了修改,那么所有包含调用该函数的文件都需要重新编译;

4.成员函数重载
在类中可以定义多个具有相同名称,但参数不同的方法,这种做法称为方法重载。参数不同可以是参数个数不同或参数类型不同,在调用重载的方法时,系统会根据给定的参数决定调用哪个同名方法;

5.const型成员函数
如果把一个函数声明为const,该成员函数不能修改他的对象的状态。使用const成员函数的主要目的是对程序员在程序设计时加以限制;对于const成员函数无论是在定义中还是原型中,关键字const都必须出现在函数头之后,如果成员函数与其定义部分分开,那么两个位置都应该加上关键字const;
5.1-使用const关键字应注意下列问题:
a.const成员函数只能修改静态数据成员;
例:
#include <iostream.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system(“pause”) or input loop /
class dog
{private:
int length;
float weight;
public:
int dog_weight(float)const;
};
int dog::dog_weight(float wt)const
{weight++;//错误,const成员函数不能改变数据成员的值
wt+=weight
length;
return int(wt);
}
b.const成员函数不能调用非const成员函数,否则编译程序会发出警告,非const成员函数可以调用const成员函数;
例:
#include <iostream.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system(“pause”) or input loop /
class dog
{private:
int length;
float weight;
public:
int dog_weight(float)const;
int dog_length();
{return length;}
};
int dog::dog_weight(float wt)const
{wt+=weight
dog_length();//不正确,const函数不能调用非const函数
return int(wt);
}
c.const对象可以调用const成员函数,但不能调用一般成员函数,一般对象既可以调用一般成员函数也可以调用const函数;

四:静态类成员
在定义类时,可以把类的成员(数据成员和成员函数)定义为静态成员(用关键字static标明),无论类创建了多少个对象,只有一个副本,这个副本为类的所有对象共享,静态成员函数只能在类的对象中有效。类的静态成员分为静态数据成员和静态成员函数;
1.静态数据成员
a.成员函数可以访问和修改静态数据成员;
例:
#include<iostream.h>
class count
{static int counter;
public:
void set_count(int k)
{cout<<counter<<endl;
};
int count::counter=0;/* 在类的定义中静态数据成员的声明不是定义,此时没有给静态数据成员分配存储空间,所以必须在类的说明之外提供定义 */
}
void main()
{count a,b;
a.display();
b.display();
a.set_count(10);
a.display();
b.display();
}


0
0
10
10

2.静态成员函数
当一个函数只访问类的静态数据成员时,可以将它定义为静态成员函数,一般情况下静态成员函数只能访问类中的静态数据成员,因为静态成员函数没有ins指针,所以不能访问非静态数据成员,同一个函数不能既有静态又有非静态两个版本;
例:
#include <iostream.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system(“pause”) or input loop */
class score
{private:
int volume;
static int totalvolume;
public:
score(int);
~score();
int fvolume();
static int ftotalvolume();
};
score::score(int x)
{volume=x;
totalvolume+=x;
}
int score::fvolume()
{return volume;}
int score::ftotalvolume()
{return totalvolume;}
int score::totalvolume=0;
int main()
{int s,count(0);
float average;
score *p;
while(1)
{cin>>s;
if(s==1)
break;
p=new score(s);
delete p;
count++;
}
cout<<score::ftotalvolume() <<endl;
average=score::ftotalvolume() /count;
cout<<average<<endl;
return 0;
}
当类的实例被释放时,静态数据成员totalvolume仍然保存原有值。静态成员函数ftotalvolume()只对静态数据成员操作;
class nobe
{public:
static void f(nobe x);
private:
int k;
};
void nobe::f(nobe x)
{cout<<k;//错误
cout<<nobe,k;//正确
}
注:在静态成员函数中不能直接引用类的非静态数据成员;

五:类的嵌套:(两种嵌套方法)
class date
{int month;
int day;
int year;
};
class employee
{char name[20];
date hireday;
};
其中类employee中包含两个成员,其中hireday是类date类型;

六:类与指针
1.this指针
this指针用于执行类的非静态成员函数。指针this指向一个类的目标,这个类目标的成员函数正在执行,当调用一个成员函数时(包括构造函数与析构函数),系统自动向他传递一个隐含的参数,该参数就是一个指向正被函数操作的对象的指针,在程序中使用关键字this引用该指针。this指针是C++实现封装的一种机制,它将数据成员和成员函数连接在一起,当一个成员函数操作一个数据成员时,用this指针表示数据成员所在的对象,当程序操作不同的对象时,this指针也指向不同的对象;
例:下面两个语句做同样的事情,第一条语句隐含使用this指针,第二条语句显示使用this指针:
void date::mo_disp()
{cout<<mo;
cout <<this ->mo;
}

例:使用this指针举例:
class location
{
int x,y;
public:
location(int xx,int yy)
{
x=xx;y=yy;
}
void assign(location &p);
int getx()
{
return x;
}
int gety()
{
return y;
}

};
void location::assign(location &p)
{if(this!=&p)
{
x=p.x;
y=p.y;
}
}
#include <iostream.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system(“pause”) or input loop */

int main()
{location ob1(2,3);
location ob2(3,4);
ob1.assign(ob2);
cout<<“x of ob1 is”<<ob1.getx() <<endl;
cout<<“x of ob1 is”<<ob1.gety() <<endl;

return 0;

}


x of ob1 is3
x of ob1 is4


Process exited after 0.1466 seconds with return value 0
请按任意键继续. . .

在该程序中,当this指针与表达式&p不指向同一个对象时,更新对象的数据;

2.new和delete运算符
在C语言中,允许使用malloc()函数动态地分配存储空间,允许使用free()函数动态地释放存储空间。在C++中使用new运算符动态分配存储空间,使用delete运算符释放存储空间;
2.1-使用new运算符分配存储空间的格式如下:
指示标识符=new 类型名(初始化值);
例:
int *p,*q;
p=new int;
q=new int(10);
定义了两个整型指针变量p和q,p和q都是指向整型变量所在存储区的指针,且q赋初值10;
2.2-创建数组类型的指针变量:
int *p,*q;
p=new int[10];
q=new int[2][3];
注意创建数组时不能初始化;
2.3-new运算符与malloc()函数相比有三大优点:
a.new运算符自动计算分配的存储空间的大小;
b.new运算符自动返回正确的指针类型;
c.new运算符可以对分配的对象进行初始化;
注:由new运算符分配的存储空间,他的生命周期是任意的,只有使用delete释放他们时,才结束生命周期。
2.4-使用delete运算符释放存储空间的格式如下:
delete 指针名;
delete q;//释放空间的大小由指针对象的类型决定;
delete []p;/ * 释放空间的大小取决于数组的大小,释放由new创建的数组时,指针名前必须加上【】,否则只释放数组的第一个元素;在【】中加入数值表示要释放空间的大小; 但给出的数值必须与数组的大小相一致; * /
例:
#include<iostream.h>
void main()
{int *p;
p=new int;//p指向新分配的整型变量
if(!p)//判断分配是否成功
cout<<“allocation fail”<<end;
*p=20;
cout<<*p;
delete p;
}

例:new与delete与构造函数和析构函数之间的关系:
#include <iostream.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system(“pause”) or input loop /
class date
{int mo,da,yr;
public:
date();
~date();
};
date::date()
{
cout<<“date constructor”<<endl;
}
date::~date()
{
cout<<“date destructor”<<endl;
}
int main(int argc, char
* argv)
{
date *dt=new date;
cout<<“process the date”<<endl;
delete dt;
return 0;
}


date constructor
process the date
date destructor


Process exited after 0.1377 seconds with return value 0
请按任意键继续. . .

注:当用new操作符初始化指针时,执行的是构造函数,当用delete操作符释放内存时,执行的是析构函数;

七:对象数组:
例:利用数组定义多个类对象:
#include <iostream.h>
using namespace std;
/* run this program using the console pauser or add your own getch, system(“pause”) or input loop /
class cube
{private:
int height,width,depth;
public:
cube()
{
cout<<“Constructor called”<<endl;
}
~cube()
{
cout<<“Destructor called”<<endl;
}
void getx(int x)
{
height=x;
}
void gety(int y)
{
width=y;
}
void getz(int z)
{
depth=z;
}
int volume()
{
return height
width*depth;
}} ;
int main()
{cube a[2];
for(int k=0;k<2;k++)
{
a[k].getx(1+k);
a[k].gety(2+k);
a[k].getz(3+k);
cout<<“volume”<<k<<"="<<a[k].volume() <<endl;
}
return 0;
}


Constructor called
Constructor called
volume0=6
volume1=24
Destructor called
Destructor called


Process exited after 0.1178 seconds with return value 0
请按任意键继续. . .

注:为每个数组元素对象执行一次析构函数,再删除数组元素之前也为每个数组元素对象执行一次析构函数;

例:对象数组初始化:
void main()
{cube a[2]={cube(1,2,3),cube(4,5,6)};
for(int k=0;k<2;k++)
cout<<“volume”<<k<<"="<<a[k],volume()<<endl;
}

八:字符串类string
string类的声明包含在头文件string.h中
1.string类有三种形式的构造函数:
a,string();//缺省构造函数,用于建立一个空串;
b,string(const char *str);//用指向字符串的指针构造一个string类的对象;
c,string(const string &s);//拷贝初始化的构造函数;
2.使用三种构造函数创建字符串:
a.string s1;/*声明一个string类的对象str,使用缺省的构造函数建立一个空串
b.string s2(“book”);//声明一个string类的对象s2,使用构造函数string(const char *str)将字符串book存入对象中 */
c.string s3(s2);/*声明一个string类的对象s2,使用构造函数string(const string &s)将s2中的字符串book存入对象s3中; */
3.在string类中还声明了一些常用的成员函数:
size_t string::length() const;//返回字符串长度的函数,不包括字符串的结束标志字符
const char *string::c_str() const;//返回字符串长度的函数,包括字符串的结束标志字符
**注:当程序中使用没有后缀.h的头文件时,要用using space std;说明。

九:C++程序的模块化组织
对于较大的C++程序通常采用模块方式组织程序。一个模块是独立的程序单元,包含数据结构和相关操作。一个模块由两部分组成,规范说明部分和实现部分。规范说明部分描述一个模块与其他模块的接口,实现部分是模块的实现细节。模块中类的说明部分作为一个单独的文件存放起来,这个文件称为头文件,扩展名为“.h”;
1.一般较大的文件可以分为三个文件来存放:
a.将类的说明作为一个头文件存放;//文件后缀为date.h(class date)
b.类的实现部分单独组成一个文件,用来存放类的成员函数的定义;//后缀为date.cpp,要将date.h和用到的C++系统库函数iostream.h包含进来;
c.在main()中实现类的应用;//applica.cpp,要将date.h和用到的C++系统库函数iostream.h包含进来;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值