1.面向对象程序设计:面向对象程序设计方法(Object-Oriented Programming,简称OOP)是20世纪90年代开始流行的一种程序设计方法,它的出现使传统程序设计思想和设计方法发生了革命性变化。
2.面向对象的特点:
1) 基于对象分解方法设计的软件在结构上更加稳定
2) 避免了传统程序设计中数据和操作的潜在的不一致性
3) 软件被看作是对象及其相互作用关系的组合,便于抽象思维
4)软件的可重用性,可靠性和安全性高
3.类(class)是对现实实体的抽象,它包括数据和操作两部分。数据用于描述对象的性质、状态,操作则用于描述该对象的行为。
4.类是对象的抽象,对象是类的实例。
5.封装性 : 指的是对象的各种外部性质同其具体的内部实现相互分离。
6.类的四大特性:抽象和封装,继承,多态。
7. 继承是派生新类的方法。通过继承,子类不仅具有父类的属性和方法,而且还具有自己独有的属性和方法。
8.多态性是指在一组具有继承关系的类层次中,同一个消息发给该类及该类的子类对象时,这些对象会作出不同的响应。
9.重载分成函数重载和运算符重载。
10.class大括号内的部分是类的成员,分别由private、public、protected三个关键字后跟冒号来指定访问属性。这3部分并非必须同时出现,可以任何顺序出现任意次。
11.Class中如果不写访问属性默认的是private,struct则默认的是公有属性。
12.Struct在没有c++时,就是相当于“c语言的类”。
13.只有类中的成员函数才能使用private的数据成员和成员函数。
14.public部分说明的数据成员或成员函数可被程序中的任何函数或语句调用。
15. protected部分说明的数据成员和成员函数是不能在类之外调用的。只有类的成员函数及其子类(派生类)可以存取protected的成员。
16.在类的定义中,类的说明部分的右边大括号后面必须有一个“;”。
17.通常将类的定义写在文件(.h文件)中,该文件称为头文件。
18.成员函数的定义写在另一个文件(.cpp文件)中,称为类文件。
19.访问对象的成员包括读写对象的数据成员和调用它的成员函数。
20.类的封装性可以防止对数据成员进行破坏。
21.代码如下
#include "Utility.h"
#include "Player.h"
void main()
{
//类普通对象的定义及使用方式
CPlayer alibaba;
//--对类内部的数据成员赋值--
alibaba.setName("alibaba");
//--获取类内部的数据成员的值--
cout<<alibaba.getName()<<endl;
cout<<alibaba.getXPos()<<endl;
cout<<alibaba.getYPos()<<endl;
cout<<alibaba.getLevel()<<endl;
cout<<alibaba.getHP()<<endl;
cout<<alibaba.getExp()<<endl;
cout<<alibaba.getAttack()<<endl;
cout<<alibaba.getDefense()<<endl;
cout<<alibaba.getMoney()<<endl;
alibaba.Attack();
//类指针型对象的定义及使用方式:
CPlayer * pPlayer = new CPlayer;
if(pPlayer)
{
pPlayer->setName("alibaba");
cout<<pPlayer->getName()<<endl;
cout<<pPlayer->getXPos()<<endl;
cout<<pPlayer->getYPos()<<endl;
cout<<pPlayer->getLevel()<<endl;
cout<<pPlayer->getHP()<<endl;
cout<<pPlayer->getExp()<<endl;
cout<<pPlayer->getAttack()<<endl;
cout<<pPlayer->getDefense()<<endl;
cout<<pPlayer->getMoney()<<endl;
pPlayer->Attack();
}
else
{
cout<<"CPlayer指针对象创建失败!"<<endl;
}
if(pPlayer)
{
delete pPlayer;
pPlayer = NULL;
}
system("pause");
}
22.在C++中可利用构造函数和析构函数来自动完成对象的初始化工作和最终的清理工作。
23.在声明类对象时,自动调用构造函数来完成对象的初始化工作。
24.当对象的生存期结束时,自动调用析构函数来完成最终的清理工作。
25.构造函数和析构函数都没有类型说明符且程序中不能直接调用,在创建和撤销对象时由系统调用自动执行。
26.对象的初始化可以通过以下方法实现:
1)直接赋值
2)公有的初始化函数
3)构造函数
4)成员初始化列表
27.C++规定在类的说明中可以包含一个或多个特殊的公有函数成员——构造函数。构造函数可以重载。
28.构造函数具有以下特征:
1)函数名与类名相同。
2)无函数(返回)类型说明,也没有返回值。
3)一个新的对象被建立时,该对象所隶属类的构造函数自动地被调用,对这个对象完成初始化工作。
4)在上一条中提到的新对象的建立包括两种情况:一种是在对象说明语句中,一种是用new函数建立新的动态对象时。
5)如果一个类说明中没有给出显式的构造函数,系统将自动给出一个缺省的(隐式的)构造函数:<类名>(void){};
6)如果说明中包括多个构造函数,一般它们有不同的参数表和函数体。
29.构造函数能对数据成员完成的初始化工作,成员初始化列表都能完成,反之则不一定。
30.在类中的常量和引用只能通过构造函数的成员初始化列表来赋值。
31.静态常量整形可以直接在类的成员列表中对其赋值。
32.静态成员是属于类的,不属于任何对象,所有对象共享一份数据。
33.静态成员变量和静态成员函数都可以通过类来直接访问,也可以通过对象去访问。
34.静态成员变量的赋值在.cpp文件中,必须在类外对其赋值初始化。
35.静态成员函数只能访问静态变量,不能访问非静态变量。
36.非静态成员函数可以访问静态变量,也可以访问非静态变量。
37.拷贝构造函数的格式:类名(const <类名> & <引用名>)
38.三种调用拷贝构造函数的情况:
1)当用类的一个对象去初始化该类的另一个对象时。
2)如果函数的形参是类的对象,调用函数时或者进行实参和形象结合时
3)如果函数的返回值是类的对象,函数调用完成返回时。
39.拷贝构造函数存在的意义:当数据成员里面有指针时,复制对象往往会连指针所指向的内存地址也一起复制,这样当一个对象发生变化时,会联动另一个对象发生变化,达不到要求,所以才通过拷贝构造函数来对其进行修改。
40.逗号表达式举例:(a=3*5,a*4)先算a=3*5再算a*4整个式的值为最后一个表达式a*4的值。、
41.#include<>从系统目录下寻找,#include””从当前工作目录下寻找。
42.代码如下图:
#include "Utility.h"
#include "Player.h"
void main()
{
类的普通对象
//CPlayer player;//创建类对象,导致构造函数被调用
//player.setName("alibaba");
//player.setHP(10000);
//cout<<player.getName()<<"的HP = "<<player.getHP()<<endl;
//类的指针对象(堆内存)
CPlayer * pPlayer1 = new CPlayer();
cout<<pPlayer1->getName()<<"的HP = "<<pPlayer1->getHP()<<endl;
pPlayer1->setName("aaa");
pPlayer1->setHP(111);
cout<<pPlayer1->getName()<<"的HP = "<<pPlayer1->getHP()<<endl;
delete pPlayer1;
pPlayer1 = NULL;
CPlayer * pPlayer2 = new CPlayer("IronMan");
delete pPlayer2;
pPlayer2 = NULL;
CPlayer * pPlayer3 = new CPlayer(200000);
delete pPlayer3;
pPlayer3 = NULL;
CPlayer * pPlayer4 = new CPlayer("SpriderMan",100);
delete pPlayer4;
pPlayer4 = NULL;
system("pause");
}
#include "Utility.h"
#include "Player.h"
//触发拷贝构造函数的情况2:类对象作为函数参数
void printObject( CPlayer player )
{
cout<<player.getHP()<<endl;
cout<<player.getMP()<<endl;
cout<<player.getExp()<<endl;
cout<<player.getLevel()<<endl;
}
//触发拷贝构造函数的情况3:类对象作为函数返回值
CPlayer Test()
{
CPlayer player001;
return player001;
}
void main()
{
CPlayer xiaoHong;
//cout<<xiaoHong.m_iHP<<endl;//反例:在类外通过类对象调用类内私有成员
cout<<xiaoHong.getHP()<<endl;
//cout<<xiaoHong.m_iMP<<endl;//反例:在类外通过类对象调用类内受保护成员
cout<<xiaoHong.m_iExp<<endl;
cout<<"xiaoHong Level = "<<xiaoHong.getLevel()<<endl;
//触发拷贝构造函数的情况1:由一个类对象创建另一个
CPlayer xiaoLv(xiaoHong);
cout<<"xiaoLv Level = "<<xiaoLv.getLevel()<<endl;
xiaoHong.setLevel(100);
cout<<"修改后小红Level = "<<xiaoHong.getLevel()<<endl;
cout<<"修改后小绿Level = "<<xiaoLv.getLevel()<<endl;
printObject(xiaoLv);
xiaoLv.setLevel(1001);
printObject(xiaoLv);
//CPlayer temp = Test();
system("pause");
}
43.使用关键字inline来定义内敛函数。
44.声明为内联函数后在编译的时候,直接执行代码,而不用再去调用函数,节省了运行时间。
45.定义在类声明之中的成员函数将自动地成为内联函数。
46.内联是以代码膨胀(复制代码)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。
47.一下情况不易使用内敛函数:如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。
如果函数体内出现循环或者递归,那么执行函数体内代码的时间要比函数调用的时间开销大,递归尤其消耗资源。
46.类的静态成员为其所有对象所共享,不管有多少对象,静态成员只有一份存于内存中。
47.在类中说明的静态数据成员属于引用性说明,必须在类的外部初始化它(且仅能说明一次)。
类型 类名::静态数据成员 = 初值;(注意在类外赋值时类型不用加static)
48.局部静态变量:在函数或块的内部说明的静态变量。
它的作用域仅局部于函数或块。
它的“生命期”却与整个程序的执行期相同。
在其它地方不能对其进行访问。
49.全局静态变量:在所有函数的外部说明
它的作用域仅局部于单文件
它的“生命期”却与整个程序的执行期相同
50.静态函数:只能在本文件的内部被调用
在其他文件中均不可见
51.静态数据成员: static修饰的类中的数据成员
为该类的所有对象所共享
52.静态函数成员:由关键字static修饰的类中的函数成员
类的静态函数成员没有this指针,不能使用const关键字
通常只在其中处理类的静态数据成员值
53.代码如下:
//#include "Utility.h"
--------内联函数---------
当某个函数可能在程序中被频繁调用,
我们应该将该函数设计为内联函数。
使用内联函数的原则1:被频繁调用
原则2:函数体比较简单:不要多于3行,不要有循环
内联函数的格式: inline 关键字
inline 返回值类型 函数名(参数表)
{
函数体
}
//inline int getSum(int a , int b)
//{
//return a+b;
//}
//void main()
//{
//int iValue1 = 10;
//int iValue2 = 20;
//int iResult1 = getSum(iValue1,iValue2);
//cout<<iResult1<<endl;
//int iValue3 = 30;
//int iResult2 = getSum(iValue2,iValue3);
//cout<<iResult2<<endl;
//system("pause");
//}
#include "Utility.h"
#include "Player.h"
CNPC * g_pPlayer = NULL;
void main()
{
//指针创建
g_pPlayer = new CNPC();
//判定有效性
if(!g_pPlayer)
{
cout<<"CPlayer指针new失败,程序结束......"<<endl;
return;
}
//使用
g_pPlayer->setHP(20000);
cout<<g_pPlayer->getHP()<<endl;
cout<<"NPC数量:"<<g_pPlayer->getInstanceCount()<<endl;
//--------------------
CNPC * pNPC1 = new CNPC();
cout<<"NPC数量:"<<pNPC1->getInstanceCount()<<endl;
CNPC * pNPC2 = new CNPC();
cout<<"NPC数量:"<<pNPC2->getInstanceCount()<<endl;
CNPC * pNPC3 = new CNPC();
cout<<"NPC数量:"<<pNPC3->getInstanceCount()<<endl;
CNPC * pNPC4 = new CNPC();
cout<<"NPC数量:"<<pNPC4->getInstanceCount()<<endl;
pNPC4->getInfo();
//-----类的静态成员在调用上有一个明显的特点-----
//可以通过 类名::静态成员 进行访问
cout<<"CNPC类的对象数量:"<<CNPC::m_iInstanceCounts<<endl;
cout<<"CNPC类的对象数量:";
CNPC::getInfo();
//使用结束后资源的回收
if(g_pPlayer)
{
delete g_pPlayer;
g_pPlayer = NULL;
}
system("pause");
}
53.常量函数成员:返回值类型 函数名(参数表)const { 函数体}又称为只读型函数,不能对类当中的数据成员进行修改。
54.对于在头文件中直接定义的常量函数成员,它也会自动的变为类内部的内联函数
55.该常量函数成员在cpp文件中实现的时候必须写上const
56.this为C++保留字,它是一个指针,在任何一个类成员函数的运行过程中,指针this 总指向当前调用者对象。
57.友元的概念是C++语言为用户提供的在局部打破程序封装和数据隐藏的手段。
58.友元又分为友元函数和友元类,关键字为friend。
59.友元函数不属于类的函数成员,可以在类内或者类外说明,有权访问和调用类内的所有数据和函数成员。
60.友元的特点:单方向,不继承,不传递
61.友元函数也是通过类的对象来访问类中的数据成员和函数成员。
62.运算符重载三个例外:1)限定符 ‘. ’和 ‘::’
2)条件运算符 ‘?:’
3)取长度运算符 ‘sizeof’
63.如果在类的内部定义的双目运算符的重载参数为一个,如果在类外定义,声明参数为两个类对象,可以将运算符重载函数声明为友元函数,这样就可以访问其私有变量了。
64.输入输出流运算符的重载!!!!!!!
65.代码如下:
#include "Utility.h"
#include "Player.h"
#include "Monster.h"
//类的指针对象:一般都是直接new一个
CPlayer * g_pPlayer = NULL;
普通函数无法访问类内的私有成员
//int getValue()
//{
//return g_pPlayer->m_iHP;
//}
//CPlayer类的友元函数,可以访问类的私有成员
int getPrivateValue()
{
return g_pPlayer->m_iHP;
}
void main()
{
//CPlayer role1;//普通对象
//CPlayer * pPlayer1 = &role1;//定义指针对象指向role1
//cout<<role1.getHP()<<endl;
//cout<<pPlayer1->getHP()<<endl;
g_pPlayer = new CPlayer();
//调用拷贝构造函数
CPlayer IronMan(*g_pPlayer);
g_pPlayer->setHP(200000);
//反例:友元函数不是类的函数成员
//g_pPlayer->getPrivateValue();
cout<<"----"<<getPrivateValue()<<endl;
delete g_pPlayer;
g_pPlayer = NULL;
//-------友元类的调用--------
CMonster * pMonster = new CMonster();
pMonster->getPlayerInfo();
system("pause");
}
//#include "Utility.h"
//
---------运算符重载----------
为某些运算符赋以全新的含义,实现特殊功能
//
//
定义角色在屏幕上的坐标
//struct stPos
//{
//int x;
//int y;
//stPos(int _x , int _y){x = _x; y = _y;}
//};
//
功能:重载+运算符,实现两个bool型数据的加法操作
//stPos operator+(stPos pos1,stPos pos2)
//{
//stPos newPos(0,0);
//newPos.x = pos1.x + pos2.x;
//newPos.y = pos1.y + pos2.y;
//return newPos;
//}
//
//void main()
//{
//stPos Pos1(1,1),Pos2(2,2);
//stPos Pos3 = Pos1+Pos2;
//
//system("pause");
//}
//#include "Utility.h"
运算符重载:1、重载为类的函数成员
2、重载为类的友元函数
//class CPlayer
//{
//private:
//int m_iHP;
//int m_iMP;
//public:
//CPlayer(int _hp,int _mp):m_iHP(_hp),m_iMP(_mp){};
//~CPlayer(){};
////当运算符重载为类的函数成员时,可省略一个参数
//CPlayer operator+ (const CPlayer & _obj)
//{
//CPlayer result(0,0);
//result.m_iHP = this->m_iHP + _obj.m_iHP;
//result.m_iMP = this->m_iMP + _obj.m_iMP;
////CPlayer result = this->m_iHP + _obj.m_iHP;
//return result;
//}
////运算符重载为类的友元函数
//friend CPlayer operator*(const CPlayer & _obj1,const CPlayer & _obj2);
//};
//
//CPlayer operator*(const CPlayer & _obj1,
// const CPlayer & _obj2)
//{
//CPlayer result(0,0);
//
//result.m_iHP = _obj1.m_iHP*_obj2.m_iHP;
//result.m_iMP = _obj1.m_iMP*_obj2.m_iMP;
//return result;
//}
//void main()
//{
//CPlayer ironMan(10000,2);
//CPlayer spriderMan(20000,3);
//CPlayer BT1 = ironMan.operator+(spriderMan);
//CPlayer BT2 = ironMan+spriderMan;
//CPlayer BT3 = BT1 * BT2;
//system("pause");
//}
#include "Utility.h"
class CCaculate
{
public:
int operator()(int a , int b)
{
return a+b;
}
};
void main()
{
CCaculate getSum; //类对象
cout<<getSum(3,5)<<endl;//类对象调用运算符重载
//仿函数
system("pause");
}