面向对象的主要特征:继承、封装、多态。
当一个类从另一个 类继承时,可以有3种派生类型:公有型(public)、保护型(protected)和私有型(private)。
方式\权限 | public | protected | private |
---|---|---|---|
public | public | protected | private |
protected | protected | protected | private |
private | private | private | private |
类的继承示例
#include <iostream>
using namespace std;
#define MAXLEN 128 // 定义一个宏
class CEmployee
{
public:
int m_ID;
char m_Name[MAXLEN];
char m_Depart[MAXLEN];
CEmployee();
void OutputName();
};
class COperator:public CEmployee
{
public:
char m_Password[MAXLEN];
bool Login();
};
CEmployee::CEmployee()
{
memset(m_Name, 0, MAXLEN);
memset(m_Depart, 0, MAXLEN);
cout << "调用非默认构造函数。" << endl;
}
void CEmployee::OutputName()
{
cout << "员工姓名:" << m_Name << endl;
}
bool COperator::Login()
{
if (0 == strcmp(m_Name, "ZL") && 0 == strcmp(m_Password, "leizi"))
{
cout << "登陆成功!" << endl;
return true;
}
else
{
cout << "登陆失败!" << endl;
return false;
}
}
void main()
{
COperator optr;
strcpy_s(optr.m_Name, "ZL");
strcpy_s(optr.m_Password, "leizi");
optr.Login();
optr.OutputName();
}
输出结果:
2、子类继承父类时,如果出现同名方法时,可能会隐藏父类的方法
class COperator :public CEmployee
{
public:
char m_Password[MAXLEN];
void OutputName();// 增加自己的输出,与父类同名
bool Login();
};
void COperator::OutputName()
{
cout << "操作员姓名:" << m_Name << endl;
}
输出结果:
从上图中可以发现,语句“optr.OutputNme()”调用的是COpertor类的OutputName方法,而不是父类的方法。如果想访问父类的OutputName方法,需要显式使用父类名
optr.CEmployee::OutputName();// 调用CEmployee类的OutputName方法。
3、如果子类隐藏了父类的方法,则父类中所有同名的方法均被隐藏
#include <iostream>
using namespace std;
#define MAXLEN 128 // 定义一个宏
class CEmployee
{
public:
int m_ID;
char m_Name[MAXLEN];
char m_Depart[MAXLEN];
CEmployee();
void OutputName();
void OutputName(const char* pchData);// 增加父类重载方法
};
class COperator :public CEmployee
{
public:
char m_Password[MAXLEN];
void OutputName();// 增加自己的输出,与父类同名
bool Login();
};
CEmployee::CEmployee()
{
memset(m_Name, 0, MAXLEN);
memset(m_Depart, 0, MAXLEN);
cout << "调用非默认构造函数。" << endl;
}
void CEmployee::OutputName()
{
cout << "员工姓名:" << m_Name << endl;
}
void CEmployee::OutputName(const char* pchData)
{
if (pchData != nullptr)
{
strcpy_s(m_Name, pchData);
cout << "设置并输出员工姓名:" << pchData << endl;
}
}
void COperator::OutputName()
{
cout << "操作员姓名:" << m_Name << endl;
}
bool COperator::Login()
{
if (0 == strcmp(m_Name, "ZL") && 0 == strcmp(m_Password, "leizi"))
{
cout << "登陆成功!" << endl;
return true;
}
else
{
cout << "登陆失败!" << endl;
return false;
}
}
void main()
{
COperator optr;
//optr.OutputName("ZL");// 错误调用
optr.CEmployee::OutputName("ZL");// 调用父类被隐藏的方法
}
4、静态绑定和动态绑定
在派生完一个子类后,可以定义一个 父类的类型指针,通过子类的构造函数为其创建对象,例如:
CEmployee *pWorker = new COperator; // 定义CEmployee父类指针,调用子类构造函数
/*
* 静态绑定:如果父类对应有方法不是虚方法,根据对象定义时的类型来确定调用哪个类的方法。
* 动态绑定:如果父类对应有方法是虚方法,根据对象运行时的类型来确定调用哪个类的方法。
* 注:在父类定义一一个虚方法,在子类改写了该方法,其中子类新改写的方法仍为虚方法,即使没有virtual关键字动态绑定示例:
*/
#include <iostream>
using namespace std;
#define MAXLEN 128 // 定义一个宏
class CEmployee
{
public:
int m_ID;
char m_Name[MAXLEN];
char m_Depart[MAXLEN];
CEmployee();
virtual void OutputName();// 定义一个虚方法
};
class COperator :public CEmployee
{
public:
char m_Password[MAXLEN];
void OutputName();// 增加自己的输出,与父类同名
bool Login();
};
CEmployee::CEmployee()
{
memset(m_Name, 0, MAXLEN);
memset(m_Depart, 0, MAXLEN);
//cout << "调用非默认构造函数。" << endl;
}
void CEmployee::OutputName()
{
cout << "员工姓名:" << m_Name << endl;
}
void COperator::OutputName()
{
cout << "操作员姓名:" << m_Name << endl;
}
bool COperator::Login()
{
if (0 == strcmp(m_Name, "ZL") && 0 == strcmp(m_Password, "leizi"))
{
cout << "登陆成功!" << endl;
return true;
}
else
{
cout << "登陆失败!" << endl;
return false;
}
}
void main()
{
CEmployee *pWorker = new COperator; // 定义CEmployee父类指针,调用子类构造函数
strcpy_s(pWorker->m_Name, "ZL"); // 设置m_Name数据成员信息
pWorker->OutputName();// 动态绑定,调用COperator类的OutputName方法
delete pWorker;
}
输出结果:
5、定义纯虚方法
纯虚方法,也就是通常说的抽象方法。一个 包含纯虚方法的类被称为抽象类,抽象类不能实例化,通常用于实现接口的定义。
class CEmployee
{
public:
int m_ID;
char m_Name[MAXLEN];
char m_Depart[MAXLEN];
CEmployee();
<strong>virtual void OutputName() = 0;// 定义一个抽象方法</strong>
};