基本概念:
对象:客观世界中任何一个事务都可以看成一个对象,每个对象有属性和行为两个要素。属性就是对象的内部状态及自身特点,行为就是改变自身状态的动作。
面向对象有3大特点,即封装、继承和多态。
封装:封装有两个作用,一个是将不同的小对象封装成一个大对象(例如一辆汽车,它是一个大对象,它由发动机、底盘、车身和轮子等这些小对象组成)。另一个是把一部分内部属性和功能对外界屏蔽。
继承:继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。在类层次中,子类只继承一个父类的数据结构和方法,称为单继承;子类继承了多个父类的数据结构和方法,称为多重继承。
多态:多态性是指相同的行为可作用于多种类型的对象上并获得不同得结果。不同得对象,收到同一消息可以产生不同得结果,这种现象称为多态性。
类:
声明/定义:
//方式一:所有定义全部放在类的内部
class Person
{
//数据成员
int index;
char Name[25];
short Age;
double salary;
//成员函数
short getAge()
{
return Age;
}
int setAge(short s_age)
{
Age = s_age;
return 0;
}
//set与get函数
//其余成员变量如上
};//注意分号
//方式二:成员函数放在类体外,需要用到域运算符"::"
class Person
{
//数据成员
int index;
char Name[25];
short Age;
double salary;
//成员函数
short getAge();
int setAge(short s_age);
//set与get函数
//其余成员变量如上
};//注意分号
short Person::getAge() //返回值类型 类名::函数名(参数)
{
return Age;
}
int Person::setAge(short s_age)
{
Age = s_age;
return 0;
}
对象的声明:
//类名 对象名表
Person p1,p2,p3;
//成员的引用
p.index;
Person *p;
p->index;
//或者
(*p).index;
构造函数: 当建立一个对象时,需要对其做一些初始化工作,这些操作刚好放在构造函数中完成。
class Person
{
Person(int index); //构造函数,与类名一样
int m_index;
int setIndex(int index);
};
Person::Person(int index) //注意没有返回值,且函数名标识符与类名标识符相同
{
m_index = index;
}
复制构造函数:用一个已经初始化的对象来新生成一个一摸一样的对象。复制构造函数就是函数的参数是一个 已经初始化的类对象。
class Person
{
Person(int index); //构造函数,与类名一样
Person(Person & copyPerson); //复制构造函数
int m_index;
int setIndex(int index);
};
Person::Person(int index)
{
m_index = index;
}
//复制构造函数
Person::Person(Person & copyPerson)
{
m_index = copyPerson.m_index;
}
调用方式:
void main()
{
Person p1(20);//index=20;
Cperson P2(p1);//p2就变得和p1一样了
}
析构函数: 析构函数与构造函数是类体定义中比较特殊的两个成员函数,二者都没有返回值,析构函数名表示符就是在类名标识符前面加“~”。析构函数的功能是用来释放一个对象的,在对象删除前,用它来做一些清理工作,它与构造函数的功能恰好相反。
class Person
{
Person();//构造函数
~Person();//析构函数
char* Message;
void ShowMessage();
};
Person::Person()
{
Message = new char[2048];
}
void Person::ShowMessage()
{
strcpy(m_Message,"Welcom to MR");
cout<<m_Message<<endl;
}
Person::~Person()
{
delete [] Message;
}
注意事项:
一个类中只能有一个析构函数;
析构函数不能重载;
构造函数和析构函数不能使用return,不用加关键字void;
构造函数和析构函数的调用环境:
(1)自动变量的作用域是某个模块,当此模块被激活时,自动变量调用构造函数,当退出此模块时,会调用析构函数;
(2)全局变量在进入main()函数之前会调用构造函数,在程序终止时会调用析构函数;
类成员:
三种类成员属性:
public:属性的成员对外可见,对内可见。
private:属性的成员对外不可见,对内可见。
protected:属性的成员对外不可见,对内可见,且对派生类是可见的。
若在定义时没有加任何关键字,默认状态类成员都在private区域。
静态类成员:
普通的类成员函数,需要通过对象来访问,不能通过类名直接访问。若将类成员定义为静态类成员,则允许使用类名直接访问,需要使用关键字“static”。
class Book
{
public:
static unsigned int Price;//静态类成员,无符号整数
};
//类外进行初始化
unsigned int Book::Price = 10;
//访问类成员函数
int main()
{
Book book;
cout<<Book::Price<<endl;//直接通过类名访问静态成员
cout<<book.Price<<endl;//通过对象访问静态成员
}
对于静态数据成员,还需要注意以下几点:
【1】定义类成员时,可将静态数据成员作为这个类的一个成员;
class Boob
{
public:
static unsigned int Price;
static Book VC_book;//静态数据成员允许定义类的所属类(Book)对象
Book *m_Book;//允许定义类的所属类型的指针类型对象
};
【2】静态数据成员可以作为类成员函数的参数
class Book
{
public:
static unsigned int Price;
int m_Pages;
void Output(int data = Price)//静态数据成员做参数
{
cout<<data<<endl;
}
};
静态成员函数:同上述静态类成员定义类似,在成员函数前加“static”就行。
类的静态成员函数只能访问类的静态数据成员,不能访问普通的数据成员;
类的静态成员函数不能定义为const成员函数,即静态成员函数末尾不能使用const关键字;
若定义的静态成员函数,它的实现代码在类体之外,则不能使用关键字“static”;
嵌套类:即在一个类中定义另外一个类。
#include <iostream>
#include <string.h>
using namespace std;
class Clist
{
public:
//嵌套类
class CNode
{
friend class Clist;//友元类,下面会介绍
private:
int Tag;
public:
char Name [100];
};//嵌套类到这结束
public:
CNode node;//定义一个CNode类型数据成员
void SetNodeName(const char *pData)
{
if(pData != NULL)
{
strcpy(node.Name,pData);//访问CNode公有数据
}
}
void setNodeTag(int tag)
{
node.Tag = tag;//访问CNode私有数据
//正常情况下,对于CNode的私有数据,外部类Clist是无法被访问的,但是在定义的时候
//将CNode类定义为Clist的友元类,这样就实现了私有类的访问
}
};
注意:被嵌套的类CNode对外是不可见的。 若非要进行访问,需要使用“Clist::CNode node”;
局部类:类的定义可以放在头文件中,可以放在源文件中,还有中情况,类的定义可以放置在函数中,这样的类被称之为局部类。
void LocalClass()
{
class Book
{
private:
int Page;
public:
void setPage(int page)
{
Page = page;
}
};
Book book;
book.setPage(300);
}
友元类: 有些时候,类会允许一些特殊的函数直接读取别的类的私有数据成员,使用friend就可以实现,这样既能保持数据的私有性,又能够使特定的类或者函数直接访问其私有成员。
友元方法:假设需要实现只允许Clist类的某个成员访问CItem类的私有成员,而不允许其他成员函数访问CItem类的私有数据。
class CItem
{
friend void Clist::Outputltem();//只允许CItem类访问Clist的OutPutltem()函数
private:
char Name[20];
};