目录
0.封装继承多态&重载隐藏覆盖
- 面向对象OOP
- 封装:代码简洁
- 继承:代码复用
- 多态:=虚函数+继承(是虚函数virtual)
重载、隐藏、覆盖:都是同名函数。都是以函数名相同条件
- 重载Overload:静态多态(成员函数重载\全局函数的重载)同一范围内(同一个类中)
- 隐藏:不是虚函数virtual
- 覆盖Override:动态多态
1.继承Inheritance
1.1继承概念
- **❗注意:**拥有≠可以访问(访问权限)父亲钱是你的,但是父亲的私房钱不一定能用
- -是私有权限、+是公有权限,#是保护权限
- 共同的功能写为基类,不同的功能写为派生类。
事例AnimalProject代码
cpp
animal.h
#pragma once
#include<iostream>
using namespace std;
class Animal
{
public:
Animal(string str);//构造函数
//私有成员有set/get函数
string GetName();
void Eat();
//private:
protected:
string name;
};
//派生类拥有基类的所有成员
class Fish : public Animal
{
public:
Fish(string str);
void Swim();
};
class Bird : public Animal
{
public:
Bird(string str);
void Fly();
};
cpp
Animal.cpp
#include "Animal.h"
Animal::Animal(string str):name(str)
{
}
string Animal::GetName()
{
return string();
}
void Animal::Eat()
{
cout << name << "吃东西" << endl;
}
Fish::Fish(string str):Animal(str)
{
}
void Fish::Swim()
{
cout << name << "游泳" << endl;
}
Bird::Bird(string str):Animal(str)
{
}
void Bird::Fly()
{
cout << name << "飞" << endl;
}
cpp
main.c
#include "Animal.h"
#include"Enemy.h"
#include"Student.h"
#include<iostream>
#include<list>
#include<fstream>
using namespace std;
int main()
{
Fish fish("大鱼海棠");
Bird bird("奥利奥");
fish.Eat();
fish.Swim();
bird.Fly();
bird.Eat();
}
1.2三种继承方式
1.3类型兼容
- 在C++中,基类与派生类之间也存在类型兼容。
- 只能子类对象赋值给父类对象✔,不能够父类对象赋值给子类对象❌
1.4父类指针指向子类对象
Animal* pf=new Fish
父类指针指向子类对象:多态和虚函数
2.派生类Derive
2.1派生类的构造函数与析构函数
【隐式调用】
2.2在派生类中隐藏基类成员函数(覆盖)
只要函数名相同就是构成隐藏,参数列表不同也是。
所以不能根据参数列表直接调用被隐藏的函数
派生的run函数把基类的run函数给隐藏起来了。
(☞多态会改变规则virtual:父类指针指向子类对象)
引用和类都是.访问。
3.多继承
4.多态及其概述
- 向不同的对象发送同一个消息(即成员函数的调用),会产生不不同的行为。
- 多态是一种调用同名函数却因上下文不同会有不同实现的一种机制
5.虚函数实现多态
5.1虚函数-事例敌人发起攻击
事例代码
cpp
Enemy.h
#pragma once
#include<iostream>
using namespace std;
class Enemy
{
public:
virtual void Attack() = 0;//纯虚函数-接口-抽象类
virtual ~Enemy();//虚析构函数
//通过基类指针释放派生类对象时。释放对象的完整性
};
class Cat:public Enemy
{
public:
Cat();
virtual void Attack();
virtual ~Cat();
};
class Dog:public Enemy
{
public:
virtual void Attack();
virtual ~Dog();
Dog();
};
cpp
Enemy.cpp
#include "Enemy.h"
Cat::Cat()
{
cout << "来了一只猫" << endl;
}
void Cat::Attack()
{
cout << "猫挠了你一把" << endl;
}
Cat::~Cat()
{
cout << "猫走了" << endl;
}
Enemy::~Enemy()
{
cout << "敌人都消失了" << endl;
}
void Dog::Attack()
{
cout << "狗咬了你一口" << endl;
}
Dog::~Dog()
{
cout << "狗走了" << endl;
}
Dog::Dog()
{
cout << "来了一只狗" << endl;
}
cpp
main.c
int main()
{
srand(time(0));
//敌人指针数组
Enemy* allEnemy[4];
//随机数创建猫狗
for (int i = 0; i < 4; ++i)
{
if (rand() % 2 == 0)
{
allEnemy[i] = new Cat;//父类指针指向子类对象
}
else
{
allEnemy[i] = new Dog;
}
}
//遍历所有敌人发起攻击
for (Enemy* pe : allEnemy)//基于范围的for循环
{
pe->Attack();
}
//释放所有敌人
for (Enemy* te : allEnemy)//基于范围的for循环
{
delete te;
}
}
5.2虚函数实现的机制
- 通过this指针访问对象,静态成员函数没有this指针所以也不能是虚函数。
5.3虚析构函数(必须!)
6.纯虚函数与抽象类abstract
接口抽象-针对接口来编程
父类指针指向子类对象。具体的派生类concrete
7.强制类型转换(动态和静态)
- 转化构造函数:只有一个参数,不是A类型的引用,而是把A类型初始化为B类型
- 类型转换函数:
- static_cast<>();
- dynamic_cast<>();
7.1静态类型转换static_cast
7.2动态类型转哈dynamic_cast
- RTTI
- vector<Person*> all
- 动态类型转换和静态类型转化
- static_cast<类型>变量;dynamic_cast<类型>变量
- typeid:类型识别
- typeid(*pa) == typeid(Dog)