(下)部分内容主要关注封装、继承和多态的操作。
传送门:
第一阶段(下):类与对象、封装、继承和多态
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; }