1.类和对象
C++时C的扩展
const限定符:C语言中是一个不能改变值的变量,const int g_nBufSize;
C++中是一个有类型描述的常量,constint g_nBufSize = 15;
const定义的常量有类型,而define定义的没有类型,编译可以对前者进行类型安全检查,const在编译时分配内存,define只是简单的替换,不分配内存。
C++申请堆空间的是new与delete运算符
int*pBuf = new int[15];
int*pNum = new int(‘f’);
C++中可以给形参赋默认值
引用即别名,与原变量地址完全一样,初始化后不可修改
cosnt引用指向const对象的引用,普通的无法引用const型数据
C++中4种不同的转换方式:const_cast:常量类型转换,主要用于去除cosnt属性,static_cast:静态类型转换,主要用于做强制类型转换,reinterpret_cast:重定义类型转换,将目标变量按照其转换类型重新定义解释并进行操作,dynamic_cast:动态类型转换
C++输入输出:dec 十进制输出,
hex16进制输出,
oct八进制输出,
setfill(c)设置填充字符,
setprecision(n)设置显示小数精度为n位
setw(n)设置域宽为n个字符,
setiosflags(ios::fixed)小数方式表示
setiosflags(ios::scientific)指数方式表示
setiosflags(ios::left)左对齐方式表示
setiosflags(ios::right)右对齐方式表示
2.类的定义,声明,应用
Clss类名
{
数据权限:
成员函数
成员变量
}
对象成员引用:对象名.成员 对象名指针->成员
成员函数定义:类体,类外,不同文件定义。
成员函数调用:通过对象调用,通过指针调用,通过引用调用
成员函数在内存中并不是和成员变量存放在一起,每个对象会单独分配对应的空间和对应的地址,每个对象也都有自己的this指针,并指向对象的首地址,通过eax寄存器保存该对象首地址,通过对象名调用对应的成员变量(编译器实际上是隐式调用了this指针),即是通过地址找到对应的变量。
成员函数的代码是放在代码区,在调用构造函数申请对象后,会保存一个跳转地址应该是一个跳转表;调用成员函数,通过寄存器ecx取到对象的首地址,通过偏移找到成员函数的这个地址,在调用成员函数时会隐式调用this指针,构造函数也可以看作是对象的成员函数,也是thiscall调用方式,所以只能是怀疑是成员函数
this指针:在每个类的成员函数中,都隐含了一个this指针,该指针指向正在调用成员函数的对象。
局部对象:作用域是局部的
全局对象:作用域在整个程序生命周期
静态对象:分内部静态对象和外部静态对象,生命周期是全局,前者作用域函数体内,后者为文件
3.构造与析构
构造函数:初始化对象
析构函数:释放对象空间
撤销顺序:先构造后析构
带参构造:利用参数化列表进行初始化
转换构造函数的作用是将一个其他类型的数据转化成一个类的对象,当一个构造函数只有一个参数,而且该参数又不是奔雷的cosnt引用时,这种构造函数称为转换构造函数。
在单个参数的构造函数之前加上explicit关键字,就会阻止转换构造,同时也阻止了在定义对象时使用的等号初始化对象
当使用赋值运算符时会调用赋值构造函数
缺省构造函数:当类中没有时会调用缺省构造函数。
拷贝构造函数:用一个对象的值创建并初始化另一个对象的方法,完成该功能的是拷贝构造函数,格式:
类名::拷贝构造函数名(类名 & 引用名)
{
…
}
其中,函数名同类名,没有返回类型,只用一个形参,且 是该类型的对象的引用。
在进行函数参数传递时,实参对象传递给形参对象,会调用拷贝构造函数,作为返回值时会调用拷贝构造函数创建一个临时对象,然后再将临时对象值给接收函数返回值的对象。
4.静态成员
静态数据成员:一处更改,将影响相关对象。
静态成员函数:类名::静态成员函数名(参数列表)或 对象名.静态成员函数名(参数列表),属于类,不属于任何对象,静态成员函数中可以直接使用静态成员函数,可以通过对象来使用非静态成员
5.友元
类具有分装性,友元机制不通过调用成员函数直接访问类的私用数据,调高运行效率。
友元声明只能出现在类定义的内部,但是在类内出现的具体位置不限,友元不是类的成员不受访问权限控制,
6.运算符重载
不能被重载的运算符有:?:
->
.
::
Sizeof
重载优先级和结合性不变,操作数个数不变,语法结构不变
通过定义一个函数来实现的,运算符符合使用习惯便于理解,运算符重载不能创造新的运算符
成员函数运算符重载:函数类型 类名::operator 符号 (参数列表){}
友元函数运算符重载:friend函数类型 operator 符号(参数列表){}
一元运算符:对象.operator符号(),或者operator符号(对象)
二元运算符:对象.operator符号(对象B),或者opertor符号(对象A,对象B)
7.派生继承
访问权限:publicprivate protected
构造顺序:先构造父类
析构顺序:先析构子类
重定义:子类修改成员功能时扩展或改写父类的成员函数
多继承易导致二义性,因此将基类定义为虚基类,在内存中则只保留一份副本。
8.多态性,虚函数
函数重载:函数名相同,参数个数,类型都不同。
虚函数与多态性
虚表指针,保存着函数的地址
静态联编,直接写入函数地址
动态联编,通过动态获取函数地址,对象地址-》虚表地址-》函数地址,
使用父类对象指针,指向子类对象,然后调用指针。
虚基类定义指针,不能实例化对象
虚析构函数,当基类指针释放时,不会调用子类析构函数,则会导致内存泄露,
因此将基类析构函数声明为虚析构函数,则调用子类析构函数释放资源。
抽象类,虚函数() =0; //纯虚函数
9.模板
函数模板定义方式
template <typename T>
void swap(T &left, T&right)
{
...
}
实例化:
swap<int>(int , int );
类模板定义方式
template <typename T>
class CStack
{
...
}
定义在.h中
void 类<T>::push(const T&data)
{
...
}
10.C++异常处理机制
try
{
…
}
catch()
{
…
}
ex1
/************************************************************************/
/* 1.编写一个程序,输出下图所示的结果
1
121
12321
1234321
123454321
12345654321
*/
/************************************************************************/
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 12; j++)
{
if (j < 6 -i || j > 6 + i)
{
cout << " ";
}
else
{
cout << i - abs(j - 6) + 1;
}
}
cout << endl;
}
return 0;
}
ex2.
/************************************************************************/
/* 2.定义一个人类,包含有姓名,年龄,身高,体重,健康指数五个量,
健康指数 = 体重 / (身高)^3 (公斤,米)
请在堆空间申请10个对象,要求为10个对象分别输入姓名,年龄,身高,
体重。之后遍历输出每个对象的姓名,年龄,健康指数,注意考虑内存泄露。
*/
/************************************************************************/
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class HumanClass
{
public:
HumanClass();
void setHuman(char *strName, int nAge, float fHigh, float fFat);
~HumanClass();
char *getstrName();
int getAge();
float getfHigh();
float getFat();
float getfHealthy();
void setstrName(char *strName);
void setAge(int nAge);
void setfHight(float fHigh);
void setFat(float fFat);
private:
char *strName;
int nAge;
float fHigh;
float fFat;
float fHealthy;
};
void HumanClass::setHuman(char *strName, int nAge, float fHigh, float fFat)
{
this->strName = strName;
this->nAge = nAge;
this->fHigh = fHigh;
this->fFat = fFat;
this->fHealthy = fFat / (fHigh * fHigh * fHigh);
}
HumanClass::~HumanClass()
{
}
char *HumanClass::getstrName()
{
return strName;
}
int HumanClass::getAge()
{
return nAge;
}
float HumanClass::getfHigh()
{
return fHigh;
}
float HumanClass::getFat()
{
return fFat;
}
float HumanClass::getfHealthy()
{
return fHealthy;
}
HumanClass::HumanClass()
{
}
void HumanClass::setstrName(char *strName)
{
this->strName = strName;
}
void HumanClass::setAge(int nAge)
{
this->nAge = nAge;
}
void HumanClass::setfHight(float fHigh)
{
this->fHigh = fHigh;
}
void HumanClass::setFat(float fFat)
{
this->fFat = fFat;
}
int _tmain(int argc, _TCHAR* argv[])
{
char strName[10] = {'\0'};
int nAge;
float fHigh;
float fFat;
HumanClass *hc = new HumanClass[10];
//HumanClass *hTmp;
for (int i = 0; i < 10; i++)
{
cout << i + 1 << ") " << "name:";
cin >> strName;
cout << endl << "nAge:";
cin >> nAge;
cout << endl << "fHigh:";
cin >> fHigh;
cout << endl << "fFat:";
cin >> fFat;
hc[i].setHuman(strName, nAge, fHigh, fFat);
}
for (int i = 0; i < 10; i++)
{
cout << i + 1 << ") name:" << hc[i].getstrName();
cout << "\tAge:" << hc[i].getAge();
cout << "\tHealthy:" << hc[i].getfHealthy() << endl;
}
delete hc;
hc = NULL;
return 0;
}
ex3.
/************************************************************************/
/*3. 设计一个类CTime类,要求其满足下述要求。
有带参数构造函数
该类中包含表示时间的时,分,秒
设置该类中的时分秒的函数,
获取该类中时分秒的三个函数:GetHour(),GetMinute()和GetSecond()
*/
/************************************************************************/
#include "stdafx.h"
#include <iostream>
using namespace std;
class CTime
{
public:
CTime();
void setHour(int nHour);
void setMinute(int nMinute);
void setSecond(int nSecond);
int GetHour();
int GetMinute();
int GetSecond();
protected:
private:
int nHour;
int nMinute;
int nSecond;
};
CTime::CTime()
{
}
void CTime::setHour(int nHour)
{
this->nHour = nHour;
}
void CTime::setMinute(int nMinute)
{
this->nMinute = nMinute;
}
void CTime::setSecond(int nSecond)
{
this->nSecond = nSecond;
}
int CTime::GetHour()
{
return nHour;
}
int CTime::GetMinute()
{
return nMinute;
}
int CTime::GetSecond()
{
return nSecond;
}
int _tmain(int argc, _TCHAR* argv[])
{
CTime ct;
int nHour;
int nMinute;
int nSecond;
cin >> nHour;
cin >> nMinute;
cin >> nSecond;
ct.setHour(nHour);
ct.setMinute(nMinute);
ct.setSecond(nSecond);
ct.GetHour();
ct.GetMinute();
ct.GetSecond();
cout << ct.GetHour() << ":" << ct.GetMinute() << ":" << ct.GetSecond() << endl;
return 0;
}
ex4.
/************************************************************************/
/* 4.继承COORD(控制台编程中使用的结构体),并添加一些成员函数,例如:
为这个新类添加 ++ 运算符重载 (前置 ++ 使X坐标加一,后置++使Y坐标加一)
添加 -- 运算符重载(前置 -- 使X坐标减一,后置--使Y坐标减一)
添加一个表示方向的成员变量,并添加朝当前方向移动一步的成员函数:
void MoveStep();
*/
/************************************************************************/
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;
class MyCOORD : public COORD
{
public:
int operator++();
int operator++(int Y);
int operator--();
int operator--(int Y);
void MoveStep();
COORD getDicUp();
void setDicUp(COORD m_dicUp);
protected:
private:
COORD m_DirectUp;
};
int MyCOORD::operator++()//前置
{
++X;
return X;
}
int MyCOORD::operator++(int Y)//后置
{
++Y;
return Y;
}
int MyCOORD::operator--()
{
--X;
return X;
}
int MyCOORD::operator--(int Y)
{
Y--;
return Y;
}
void MyCOORD::MoveStep()
{
m_DirectUp.Y++;
}
COORD MyCOORD::getDicUp()
{
return m_DirectUp;
}
void MyCOORD::setDicUp(COORD m_dicUp)
{
this->m_DirectUp = m_dicUp;
}
int _tmain(int argc, _TCHAR* argv[])
{
MyCOORD mc;
COORD cd;
cd.X = 10;
cd.Y = 10;
mc.setDicUp(cd);
cout << "位置:";
cout << "(" << mc.getDicUp().X << "," << mc.getDicUp().Y << ")" << endl;
mc.MoveStep();
cout << "向上移动一步:";
cout << "(" << mc.getDicUp().X << "," << mc.getDicUp().Y << ")" << endl;
return 0;
}
ex5.
/************************************************************************/
/*5. 编写一个程序,设计一个汽车类vehicle,包含的数据成员有车轮个数wheels和车重weight
小车类car是vehicle的私有派生类其中包含载人数passenger_load
卡车类truck是vehicle的私有派生类其中包含在人数passenger_load和载重量payload
每个类都有相关数据的输出方法。
*/
/************************************************************************/
#include "stdafx.h"
#include <iostream>
using namespace std;
class vehicle
{
public:
vehicle(){}
vehicle(int wheels, int weight) : wheels(wheels), weight(weight){}
void ShowWheels()
{
cout << "vehicle -> wheels: " << wheels << endl;
}
void ShowWeight()
{
cout << "vehicle -> weight: " << weight << endl;
}
protected:
private:
int wheels;
int weight;
};
class car : private vehicle
{
public:
car(int passenger_load) : passenger_load(passenger_load){}
void ShowPassengerLoadcar()
{
cout << "car -> passenger_load: " << passenger_load << endl;
}
protected:
private:
int passenger_load;
};
class truck : private vehicle
{
public:
truck(int passenger_load, int payload) : passenger_load(passenger_load), payload(payload){}
void ShowPassengerLoadtruck()
{
cout << "truck -> passenger_load: " << passenger_load << endl;
}
void ShowPayLoad()
{
cout << "truck -> payload: " << payload << endl;
}
protected:
private:
int passenger_load;
int payload;
};
int _tmain(int argc, _TCHAR* argv[])
{
vehicle vc(4, 200);
car c(50);
truck t(30, 200);
vc.ShowWeight();
vc.ShowWheels();
c.ShowPassengerLoadcar();
t.ShowPassengerLoadtruck();
t.ShowPayLoad();
return 0;
}
ex6.
/************************************************************************/
/*6. 编写一个学生和教师数据输入和显示程序
学生数据有编号,姓名,班号和成绩
教师数据有编号,姓名,职称和部门
要求将编号,姓名的输入和显示设计成一个类person,并作为学生数据操作类
student和教师数据操作类teacher的基类
*/
/************************************************************************/
#include "stdafx.h"
#include <iostream>
using namespace std;
class person
{
public:
person(){}
person(int nID, char *szName) : nID(nID), szName(szName){}
int getID()
{
return this->nID;
}
char* getName()
{
return this->szName;
}
void setID(int nID)
{
this->nID = nID;
}
void setName(char *szName)
{
this->szName = szName;
}
protected:
private:
int nID;
char *szName;
};
class student : public person
{
public:
student(){}
int getClassID()
{
return this->nClassID;
}
int getGrade()
{
return this->grade;
}
void setClassID(int nClassID)
{
this->nClassID = nClassID;
}
void setGrade(int grade)
{
this->grade = grade;
}
protected:
private:
int nClassID;
int grade;
};
class teacher : public person
{
public:
teacher(){}
char *getPosition()
{
return this->position;
}
char *getDepart()
{
return this->depart;
}
void setPosition(char *position)
{
this->position = position;
}
void setDepart(char *depart)
{
this->depart = depart;
}
protected:
private:
char *position;
char *depart;
};
int _tmain(int argc, _TCHAR* argv[])
{
student stu;
teacher tea;
//stu
cout << "请输入学生编号:";
int nID = 0;
cin >> nID;
stu.setID(nID);
cout << "请输入学生姓名:";
char szName[100] = {'\0'};
cin >> szName;
stu.setName(szName);
cout << "请输入学生班号:";
int nClassID = 0;
cin >> nClassID;
stu.setClassID(nClassID);
cout << "请输入学生成绩:";
int grade = 0;
cin >> grade;
stu.setGrade(grade);
cout << "*******************" << endl;
cout << "学生编号为:" << stu.getID() << endl;
cout << "学生姓名为:" << stu.getName() << endl;
cout << "学生班号为:" << stu.getClassID() << endl;
cout << "学生成绩为:" << stu.getGrade() << endl;
cout << "*******************" << endl;
//tea
cout << "请输入教师编号:";
cin >> nID;
tea.setID(nID);
cout << "请输入教师姓名:";
cin >> szName;
tea.setName(szName);
cout << "请输入教师职称:";
char position[100] = {'\0'};
cin >> position;
tea.setPosition(position);
cout << "请输入教师部门:";
char depart[100] = {'\0'};
cin >> depart;
tea.setDepart(depart);
cout << "*******************" << endl;
cout << "教师编号为:" << tea.getID() << endl;
cout << "教师姓名为:" << tea.getName() << endl;
cout << "教师职称为:" << tea.getPosition() << endl;
cout << "教师部门为:" << tea.getDepart() << endl;
cout << "*******************" << endl;
return 0;
}
ex7.
/************************************************************************/
/*7提高.编写一个栈的类模板,实现栈的push,和pop操作,提供对任何数据类型的插入
和删除。(先进后出)
*/
/************************************************************************/
#include "stdafx.h"
#include <iostream>
using namespace std;
template <class T>
class Stack
{
public:
Stack()
{
StackBase = new T[10];
StackPoint = StackBase;
}
~Stack(){}
void push(T data)
{
if (this->StackPoint == this->StackBase + 10)
{
cout << "栈满!" << endl;
}
*this->StackPoint = data;
this->StackPoint++;
}
T pop()
{
if (this->StackBase == this->StackPoint)
{
cout << "栈空!" << endl;
}
this->StackPoint--;
T data = *this->StackPoint;
return data;
}
T *StackPoint;
T *StackBase;
protected:
private:
};
int _tmain(int argc, _TCHAR* argv[])
{
Stack<int> st;
st.push(5);
st.push(6);
cout << *st.StackBase << *st.StackBase + 1 << endl;//可以使用循环遍历输出
st.pop();
cout << *st.StackPoint << endl;//可以使用循环遍历输出
return 0;
}