(下)部分内容主要关注封装、继承和多态的操作。
传送门:
第一阶段(下):类与对象、封装、继承和多态
4.类及其使用
类的学习需要掌握的内容如下:
用一个例子来解释:
新建lei.h头文件和lei.cpp源文件
代码如下:
//lei.h
class Date {
public:
void SetDate(int a, int b, int c);
void ShowDate();
private:
int year;
int month;
int day;
};
//lei.cpp
#include "stdafx.h"
#include "lei.h"
#include <iostream>
using namespace std;
void Date::SetDate(int a, int b, int c)
{
year = a;
month = b;
day = c;
}
void Date::ShowDate()
{
cout << year << "年" << month << "月" << day << "日" << endl;
}
在main函数中
int main()
{
Date test;
test.SetDate(2018, 6, 2);
test.ShowDate();
return 0;
}
结果如下:
这里特别注意private和protect两种访问形式的区别,一般只有在派生类时才有所体现,派生自基类(如例中的Date)的类访问基类时,可以访问protect成员,而不能访问private成员。
构造函数:一般用于初始化成员变量的值,如本例中可以将SetDate(int a, int b, int c)
函数作为构造函数,在创建一个实例后,自动进行初始化赋值。
Date::Date(int a, int b, int c)
{
year = a;
month = b;
day = c;
}
Date::~Date()
{
cout << "Destroy" << endl;
}
void Date::ShowDate()
{
cout << year << "年" << month << "月" << day << "日" << endl;
}
int main()
{
Date test(2018,6,1); //实例化时直接初始化
test.ShowDate();
return 0;
}
5.封装
封装的定义以及需要掌握的内容如下:
5.1 this指针
只能在类的成员函数中进行调用,如下所示
void Date::SetDate(int year, int month, int day)
{
this->year = year; //通过this指针访问类中的私有变量year,并与形参中的year进行区分
this->month = month;
this->day = day;
}
5.2 友元函数friend
可以访问与其有friend关系中类的私有成员,实现类间的数据共享,定义如下。
5.2.1 全局友元函数(类与普通函数之间的数据共享)
.h文件:
class Date {
public:
void SetDate(int year, int month, int day);
void ShowDate();
friend void Call(Date &); //全局友元函数
private:
int year;
int month;
int day;
};
.cpp文件
#include "stdafx.h"
#include "lei.h"
#include <iostream>
using namespace std;
void Date::SetDate(int year, int month, int day)
{
this->year = year;
this->month = month;
this->day = day;
}
void Call(Date &t)
{
cout<<"Call:"<<t.year << "年" << t.month << "月" << t.day << "日" << endl; 、、可以访问Date类的数据
}
main函数中
int main()
{
Date test;
test.SetDate(2018,6,2);
Call(test); //输出2018年6月2日
return 0;
}
5.2.2 友元成员函数(不同类之间的数据共享)
.h文件:
class Time; //先声明
class Date {
public:
//Date();
void SetDate(int year, int month, int day);
//~Date();
//void ShowDate();
void Call(Time &); //声明成员函数
private:
int year;
int month;
int day;
};
class Time {
public:
Time(int = 2018, int = 1, int = 1);
friend void Date::Call(Time&); //将成员函数Call作为本类的友元函数
private:
int y;
int m;
int d;
};
.cpp文件
#include "stdafx.h"
#include "lei.h"
#include <iostream>
using namespace std;
void Date::SetDate(int year, int month, int day)
{
this->year = year;
this->month = month;
this->day = day;
}
void Date::Call(Time &d)
{
cout<<"Date中的成员变量:"<<year << "年" << month << "月" << day << "日" << endl;
cout << "Time中的成员变量:" << d.y << "年" << d.m << "月" << d.d << "日" << endl;
}
Time::Time(int y, int m, int d)
{
this->y = y;
this->m = m;
this->d = d;
}
main函数中
int main()
{
Time t;
Date d;
d.SetDate(2018,6,2);
d.Call(t);
return 0;
}
输出结果如下,可以看到Call(Time &d)函数可以访问Time中的private变量
6.继承与派生
如果在开发中已经定义了一个名为A的类,又想新建一个名为B的类,但B中的大部分功能可以通过A实现,此时可以让B继承A,或者说B由A派生而来。
格式为:class 派生类名: [继承方式]基类名
继承方式如下:
- 公有继承:基类中的公有、私有成员在派生类中依旧保持原有的访问属性。
- 私有继承:此时基类的公有成员和保护成员相当于派生类中的私有成员,派生类的成员函数能访问,基类中的私有成员在派生类中是不可访问的。
- 保护继承:基类的公有保护成员在派生类中成为保护成员,基类私有成员仍为私有成员。主要作用是保护基类中的公有成员。
公有继承示例:
.h文件
class Date {
public:
//Date();
void SetDate(int year, int month, int day);
//~Date();
void ShowDate();
private:
int year;
int month;
int day;
};
class Date1 : public Date //继承自Date,其中public表示公有继承
{
public:
void SetSec(int x); //新增成员函数
void GetFromDate();
private:
int sec; //新增成员变量
};
.cpp文件
#include "stdafx.h"
#include "lei.h"
#include <iostream>
using namespace std;
void Date::SetDate(int year, int month, int day)
{
this->year = year;
this->month = month;
this->day = day;
}
void Date::ShowDate()
{
cout << year << "年" << month << "月" << day << "日" << endl;
}
void Date1::SetSec(int x)
{
sec = x;
}
main函数
int main()
{
Date1 d1;
d1.SetDate(2018, 6, 2); //访问基类中的两个成员函数
d1.ShowDate();
return 0;
}
私有继承示例如下:
.h文件
class Date {
public:
//Date();
void SetDate(int year, int month, int day);
//~Date();
void ShowDate();
private:
int year;
int month;
int day;
};
class Date1 : private Date //继承自Date,其中private表示私有
{
public:
void GetFromDate();
};
.cpp文件
#include "stdafx.h"
#include "lei.h"
#include <iostream>
using namespace std;
void Date::SetDate(int year, int month, int day)
{
this->year = year;
this->month = month;
this->day = day;
}
void Date::ShowDate()
{
cout << year << "年" << month << "月" << day << "日" << endl;
}
void Date1::GetFromDate()
{
SetDate(2018, 6, 1); //通过Date1中的公有函数调用Date中的公有函数(此时 SetDate()和 ShowDate()相当于Date1中的私有成员函数)
ShowDate();
}
main函数
int main()
{
Date1 d1;
d1.GetFromDate();
return 0;
}
7.多态
多态指的是不同功能的函数可以用同一个函数名,不同对象调用这个函数时会产生不同的效果,多态分为以下两种。
- 静态多态性(函数重载和运算符重载)
- 动态多态性(程序运行过程中动态确定,通过虚函数实现)
7.1 静态多态性
7.1.1 函数重载
函数重载的示例如下
.h文件
#include<string>
using namespace std;
class Date {
public:
//Date();
void SetDate(int year, int month, int day);
//~Date();
void ShowDate();
void ShowDate(string str);
private:
int year;
int month;
int day;
};
.cpp文件
#include "stdafx.h"
#include "lei.h"
#include <iostream>
#include<string>
using namespace std;
void Date::SetDate(int year, int month, int day)
{
this->year = year;
this->month = month;
this->day = day;
}
void Date::ShowDate()
{
cout << year << "年" << month << "月" << day << "日" << endl;
}
void Date::ShowDate(string str)
{
cout << str << endl;
}
main函数
#include "stdafx.h"
#include<iostream>
#include "lei.h"
using namespace std;
int main()
{
Date d;
d.SetDate(2018, 6, 1);
d.ShowDate();
d.ShowDate("二零一八年六月一日");
return 0;
}
输出为
7.1.2 运算符重载
运算符重载可以修改现有的运算符,实现对类中数据进行操作的功能。
<返回类型说明符> operator <运算符符号>(<参数表>)
{
<函数体>
}
示例:
.h文件
#include<string>
using namespace std;
class Calculator {
public:
Calculator(); //用于value的初始化
void operator ++ (); //自增运算符
void operator--(); //自减运算符
int operator()(); //函数运算符
private:
unsigned int value;
};
.cpp文件
#include "stdafx.h"
#include "lei.h"
#include <iostream>
#include<string>
using namespace std;
Calculator::Calculator()
{
value = 0;
}
void Calculator::operator++()
{
if (value < 65535)
value++;
else
{
cout << "\noverflow" << endl;
}
}
void Calculator::operator--()
{
if (value > 0)
value--;
else
{
cout << "\nunderflow" << endl;
}
}
int Calculator::operator()()
{
return value;
}
.main函数
int main()
{
Calculator cal ;
for (int i = 0; i < 5; i++)
{
++cal; //调用自加运算符,执行类中value数据的自加
cout << "\n cal = " << cal(); //调用函数运算符,执行类中value数据的输出
}
for (int i = 0; i < 5; i++)
{
--cal; 调用自减运算符,执行类中value数据的自减
cout << "\n cal = " << cal();
}
return 0;
}
输出如下
7.2 虚函数
在类的继承中,不同派生类可以出现名字相同、参数个数和类型都相同而功能不同的函数,虚函数用以区分这些函数。
格式:virtual <返回类型> 函数名(<形参>)
.h文件
#pragma once
#include<string>
using namespace std;
class A {
public:
virtual void ShowMessage();//基类中声明虚函数
};
class B :public A //B继承A
{
public:
virtual void ShowMessage();
};
class C :public B //C继承B
{
public:
virtual void ShowMessage();
};
.cpp文件
#include "stdafx.h"
#include "lei.h"
#include <iostream>
#include<string>
using namespace std;
void A::ShowMessage()
{
cout << "This is A!" << endl;
}
void B::ShowMessage()
{
cout << "This is B!" << endl;
}
void C::ShowMessage()
{
cout << "This is C!" << endl;
}
main函数
#include "stdafx.h"
#include<iostream>
#include "lei.h"
using namespace std;
int main()
{
A *a = new A();
B *b = new B();
C *c = new C();
a->ShowMessage();
b->ShowMessage();
c->ShowMessage();
return 0;
}