1. 对象
一个对象往往是由一组属性和一组行为共同描述对象的每个属性都具有属性值,它们结合在一起反映对象的状态
2. 类
具有相同属性和行为的对象的抽象就是类类是对象的抽象,对象是类的实例类也具有属性,它是类中所有对象的属性抽象,用数据成员来描述类的属性。类同时也具有行为,它是类中所有对象的行为抽象,用成员函数来描述类的行为
3. 方法和消息
类中行为的实现过程即类的方法,也是类的成员函数
对象之间需要相互沟通,沟通的途径就是向对象发送消息,通过调用成员函数来实现发送消息
2.1.2 面向对象程序设计方法的基本原理1. 抽象
抽象是从众多的事物中抽取出共同的、本质的特征
抽象是简化复杂问题的途径,它可以为具体问题找到恰当的类定义
2. 封装
封装就是把对象的属性和行为结合成一个独立的单位,并尽可能隐蔽对象的内部细节封装在对象的内部与外界之间形成一道屏障,内部与外部的联系只能通过外部接口实现
3. 继承
继承是指一个对象可以获得另一个对象的特性的机制(如认识轮船的特征后,由于客轮是轮船的特殊种类,因此客轮具有轮船的特征。)
4. 多态性
不同的对象调用相同名称的函数,可以导致完全不同的行为的现象称为多态性利用多态性,程序员只须进行一般形式的函数调用,函数的实现细节由接受函数调用的函数体确定,这样提高了解决复杂问题的能力 2.2 类和对象 2.2.1 类的定义
类的定义格式一般分为声明部分和实现部分 ,类的一般定义格式:
class 类名
{
public:
成员函数或数据成员的声明
protected:
数据成员或成员函数的声明
private:
数据成员或成员函数的声明
};
成员函数的类外实现 //如果一个成员函数在类中
//声明的时候就已经实现了,
//那它就无须在类外实现。
2.2.2 成员函数的实现
成员函数的实现一般有两种方式,一种是类内实现,另一种是类外实现类的每一个成员函数在声明时就定义了实现代码,这种形式就叫成员函数在类内实现类外实现就是把成员函数的实现代码放到类声明外 2.2.3 对象的创建
创建对象一般应该在定义一个类之后去做。一般的语法格式如下:
类名 对象名;
例如,在定义了Date类之后,可以创建一个名为newDate的日期对象:
Date newDate;2.2.3 类成员的访问
1. 类成员的一般访问形式
当建立一个普通对象时,可以通过对象名和句点符号去访问类的公有成员,相关的语法格式如下:
对象名.数据成员名 // 访问数据成员 对象名.成员函数名(参数表) // 访问成员函数
2. 类成员的访问权限
类成员具有访问权限,访问权限通过在类成员前面的关键字来定义。关键字private、protected和public代表访问权限分别是私有、保护和公有访问权限,其后定义的成员分别称为私有成员、保护成员和公有成员。访问权限用于控制对象的某个成员在程序中的可访问性,访问权限遵守如下的访问规则:
公有成员:类外可访问这些公有成员
私有成员:私有成员只能被类成员函数所访问,类外不可访问这些公有成员
保护成员:保护成员只能被该类及其派生类的成员函数所访问,不能在类外访问
2.3 构造函数和析构函数 2.3.1 构造函数构造函数的作用就是在对象被创建时为其分配内存空间,利用给定的值去初始化对象的数据成员,把对象构造成一个特定的状态声明一个构造函数的格式:
类名(参数表);
构造函数是类的一个特殊成员函数,它的函数名与类名相同,不具有返回类型。当创建一个新对象时,系统会自动调用构造函数 2.3.2 重载构造函数
在一个类中,可以重载多个同名的构造函数,只是它们的参数表不同
例
class Date
{
public:
Date(); //声明一个无参数的构造函数
Date(int y, int m, int d); //声明一个带三个参数的构造函数
void SetDate(int y, int m, int d) ;
bool IsLeapYear();
void Print();
private:
int year, month, day; //声明日期类的属性:年、月、日
};
2.3.3 带默认参数的构造函数
前面已经介绍过带默认参数的函数,它不仅可以是全局函数,其实也可以是类的成员函数,包括构造函数
例
class Date
{
public:
Date(int y=2000, int m=1, int d=1); //声明带三个参数的构造函数
void SetDate(int y, int m, int d) ;
bool IsLeapYear();
void Print();
private:
int year, month, day; //声明属性:年、月、日
};
int main()
{
Date date1; //创建对象没有提供实参,参数取默认值
Date date2(2012, 10, 1); //调用带参数构造函数,采用实参值来初
// 始化数据成员
date1.Print();
if (date1.IsLeapYear()) cout<<"此年是闰年"<
特别注意:
//下面这个程序存在歧义。
class CDemo
{
public:
CDemo() { a = 0; }
CDemo(int x=1) { a = x; }
private:
int a;
};
int main()
{
CDemo d1(10); //调用带默认参数的构造函数,将a初始化为10
// CDemo d2; //既可以调用无参构造函数,又可以调用带默认参
//数的构造函数,出现歧义!
return 0;
}
2.3.4 拷贝构造函数
拷贝构造函数使用一个已创建好的对象(由拷贝构造函数的参数指定)去初始化一个正在创建的同类对象声明拷贝构造函数的一般语法格式:
类名(const 类名 &对象名);
例
class CPoint
{
public:
CPoint(int x1, int y1); //声明构造函数
CPoint(const CPoint &obj); //声明拷贝构造函数
int GetX();
int GetY();
private:
int x; //水平坐标
int y; //垂直坐标
};
CPoint::CPoint(int x1, int y1)
{
x = x1;
y = y1;
}
CPoint::CPoint(const CPoint &obj) //拷贝构造函数
{
x = obj.x;
y = obj.y;
}
int CPoint::GetX() //通过接口间接访问x坐标
{
return x;
}
int CPoint::GetY() //通过接口间接访问y坐标
{
return y;
}
int main()
{
CPoint a(20, 50);//调用构造函数,创建了一个坐标为(20,50)的点a
CPoint b(a); //系统调用拷贝构造函数,利用点a克隆点b
CPoint c = a; //系统调用拷贝构造函数,利用点a克隆点c
cout << "a (" << a.GetX() << "," << a.GetY() << ")" << endl;
cout << "b (" << b.GetX() << "," << b.GetY() << ")" << endl;
cout << "c (" << c.GetX() << "," << c.GetY() << ")" << endl;
return 0;
}
2.3.5 析构函数
对象对象消亡时需要做一些扫尾工作。析构函数来完成此项工作
声明一个析构函数的语法格式:
~类名();
析构函数的函数名是类名前面多加了一个“ ~”。它没有参数和返回值
先创建后析构
2.4 对象数组
对象数组就是数组里的每个元素都是同一个类的对象对象数组的每个元素一般调用无参构造函数或所有参数都带有默认值的构造函数
CPoint *p = new CPoint[6];
// 只能调用无参构造函数或所有参数都带有默认值的
// 构造函数
CPoint a[] = {CPoint(1, 1), CPoint(2, 2), CPoint(3, 3)};
// 调用带参构造函数,不使用参数默认值,这是惟一
// 例外情况
2.5 对象指针
对象指针就是一个指向对象的指针 。
2.5.1 指向对象的指针
指向对象的指针(即对象指针)采用箭头操作符“->”来访问该指针所指向的对象的数据成员或成员函数 ,具体格式如下:
对象指针名->数据成员名
对象指针名->成员函数名(参数表)
例
#include "sclass2_11_rectangle.h"
int main()
{
Rectangle *rp= new Rectangle(10,5); //定义对象指针(Rectangle)
rp->Print(); //调用rp所指向的对象的成员函数print()
rp->SetSize(45, 20); //调用rp所指向的对象的成员函数SetSize(45, 20)
cout<<"长45宽20的长方形的面积是"<< rp->GetArea()<
2.5.2 this指针
对于同类对象,它们各自拥有一套数据成员,分别占用存储空间。而类的成员函数对于类的所有对象而言都只有一份。当不同的对象调用相同的成员函数时,为识别函数所操纵的数据成员所属的对象,每个类都拥有一个自动生成的私有成员this指针,用来指向正在调用某个成员函数的对象。
#ifndef __SCLASS2_12_POINT_H__
#define __SCLASS2_12_POINTE_H__
#include
using namespace std;
class CPoint
{
public:
CPoint(){}
~CPoint(){}
CPoint(float, float);
void Move(float, float);
//为了便于类外访问,以下声明公有数据成员
float x;
float y;
};
#endif
//sclass2_12_point.h文件结束
#include "sclass2_12_cpoint.h"
CPoint::CPoint( float x, float y)
{
this->x = x;
this->y = y;
}
void CPoint::Move(float x, float y)
{
this->x=x;
this->y=y;
}
//sclass2_12_cpoint.cpp文件结束
2.6 静态成员
要在同类的多个对象之间实现数据共享,而又避免使用全局变量,那么可以用类的静态数据成员来实现
2.6.1 静态数据成员
声明为static的数据成员就是静态数据成员,为该类的所有对象共享
声明静态数据成员的语法格式如下:
static 数据类型 静态数据成员名;
静态数据成员的初始化语法格式如下:
数据类型 类名::静态数据成员名 = 初始值;
访问静态数据成员的语法形式:
类名::静态数据成员名;
例
class Point
{
public:
Point()
{
x=0;
y=0;
counter++; //当创建对象时,计数器的值递增一个
}
~Point()
{
counter--; //当析构对象时,计数器的值递减一个
}
....
private:
float x;
float y;
public:
static int counter;
};
int Point::counter=0; //在类外初始化静态数据成员counter
2.6.2 静态成员函数
C++采用静态成员函数负责对静态数据成员的存取;
静态成员函数的声明是在成员函数声明加上static关键字:
static 返回值类型 函数名(参数表);
静态成员函数通过作用域分辨符来访问,语法格式如下:
类名::静态成员函数名(参数表)
静态成员函数不能直接访问普通数据成员,this指针为普通数据成员,静态成员函数也不能访问this指针
例:
class Point
{
public:
Point()
{
x=0;
y=0;
counter++; //当创建对象时,计数器的值递增一个
}
~Point()
{
counter--; //当析构对象时,计数器的值递减一个
}
....
static int GetCounter()
{
return counter;
// return counter + x + y; //错,静态成员函数不能直接
//访问普通数据成员
}
private:
float x;
float y;
static int counter;
};
int Point::counter=0; //在类外初始化静态数据成员counter
2.7 友元关系
“友元” 就是为类设定“朋友”。只要是“朋友”关系,类中隐藏的私有数据成员就可以对它公开类的友元既可以是函数——友元函数,也可以是另一个类——友元类
2.7.1 友元函数
友元函数由关键字friend修饰,在类中声明友元函数的格式如下:
friend 返回值类型 函数名(参数表);
虽然在类中声明,但不属于该类的成员函数
友元函数可以是普通函数,也可以是其他类的成员函数
例
class CPoint
{
public:
CPoint(double xx = 0, double yy = 0)
{
x = xx;
y = yy;
}
double GetX()
{
return x;
}
double GetY()
{
return y;
}
friend double FDist(CPoint *p1, CPoint*p2);
private:
double x, y;
};
……
double FDist( CPoint *p1, CPoint *p2 )
{ //由于是友元关系,p1、p2可以直接访问所指对象的私有成员x和y
double x = p1->x - p2->x;
double y = p1->y - p2->y;
return sqrt(x*x + y*y);
};
友元函数注意事项
友元函数可以直接访问该类的所有成员,但它不是该类的成员函数如果友元函数是其他类的成员函数,那么在声明友元关系的时候,只需要在该成员函数的函数名前面加上“类名::”,例如:
class A
{
……
friend void B::Function( ); //类B的成员函数Function( )声明为
//类A的友元函数,在Function函数体中就可
//以直接访问类A的私有成员了
……
};
2.7.2 友元类
如果类B是类A的友元类,那么类B中的所有成员函数都是类A的友元函数,可以访问类A的所有成员
友元类的声明语句如下:
class B; // 前向引用声明,此处不需要
class A
{
……
friend class B; // B为A的友元类
……
};
2.8 共享数据的保护
数据共享不同程度地破坏了数据的安全对于既需要共享、又需要防止被修改的数据应该声明为常量关键字const可以修饰对象,称之为常对象
2.8.1 常引用
在声明引用时用const修饰,那么该引用就是一个常引用
如果用常引用做形参,那么可以保证实参不会意外地被修改。声明常引用的一般语法形式有如下两种方式:
const 数据类型 &引用名 = 变量名;
数据类型 const &引用名 = 变量名;
2.8.2 常对象
在声时对象时用const关键字来修饰这个对象,这样的对象称为常对象
常对象的数据成员值在对象的整个生命周期内都不会被改变
声明常对象的语法形式如下两种方式:
类名 const 对象名(实参表);
const 类名 对象名(实参表);
2.8.3 常成员
1. 常成员函数
常对象不能调用普通成员函数的。为确保常对象调用函数的安全性,C++提出来一种特殊的成员函数——常成员函数
常成员函数就是用const关键字说明的函数,其格式如下:
返回类型 函数名(参数表) const
常成员函数不能修改数据成员它们的值
常对象只能调用类的常成员函数及类的静态成员函数
2. 常数据成员
用const来修饰的数据成员被称为常数据成员
任何成员函数都不能修改数据成员的值
构造函数对该数据成员的初始化也比较特殊,只能通过初始化列表来完成,初始化列表的一般格式如下:
:数据成员1(值1), 数据成员2(值2),…



