网龙C++游戏训练营培训课程第一阶段(下):类与对象、封装、继承和多态

(下)部分内容主要关注封装、继承和多态的操作。
传送门:
第一阶段(下):类与对象、封装、继承和多态

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.多态

多态指的是不同功能的函数可以用同一个函数名,不同对象调用这个函数时会产生不同的效果,多态分为以下两种。
  1. 静态多态性(函数重载和运算符重载)
  2. 动态多态性(程序运行过程中动态确定,通过虚函数实现)

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;
}
输出如下


猜你喜欢

转载自blog.csdn.net/s1314_JHC/article/details/80558106