多态概念
多态是面向对象编程中的一个重要概念,它允许在基类的指针或引用指向派生类对象时,调用不同的函数实现。换句话说,多态是指同一接口在不同对象中有不同的实现方式。
多态的基本分类:
① 编译时多态(静态多态):通过函数重载和运算符重载来实现。
② 运行时多态 (动态多态):通过继承和虚函数来实现。
对象多态
① 向上转型 父类==>子类 人是动物
② 向下转型 子类==>父类 动物是人 相当于用子类代替父类 (大神和沙雕之间二象性)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
#include <iostream>
class Animal { public: int age; };
class Human :public Animal { public: int Money; void doit() { std::cout << "Do it~!!!"; } };
int main() { Human laow{}; laow.age = 50; laow.Money = 3000;
Animal* anm1 = &laow; Human* human = (Human*)anm1;
human->doit(); }
|
方法多态
① 静态多态: 函数重载、函数模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #include <iostream>
class Animal { public: int age; };
class Human :public Animal { public: int Money; void doit() { std::cout << "Do it~!!!"; } };
void BeAct(Human* R) {
} void BeAct(Animal* anm) {
}
int main() { Human laow; Animal dog;
BeAct(&laow); BeAct(&dog); }
|
② 动态多态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
#include <iostream>
class Animal { public: int age; void BeAct(Animal* anm) { std::cout << "动物被攻击!!" << std::endl; } };
class Human :public Animal { public: int Money; void doit() { std::cout << "Do it~!!!"; } void BeAct(Animal* anm) { std::cout << "人物被攻击!!" << std::endl;
} };
int main() { Human laow; Animal dog;
int id; Animal* bA; std::cin >> id; if (id) { bA = &dog; } else bA = &laow; bA->BeAct(&dog); }
|
virtual关键字
它是一个在基类中声明,并且希望在派生类中重写(或覆盖)的方法。通过虚函数,可以实现多态性,使得程序能够在运行时根据对象的实际类型来调用适当的函数,而不是在编译时就决定调用哪个函数。
override 后缀可以强制要求检查函数是重载
final 后缀可以终止函数的重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
#include <iostream> class MoveObject { public: int x; int y; void virtual Move();
virtual MoveObject* Move1() { x++; y++; return this; } };
void MoveObject::Move() { x++; y++; }
class NPCObject:public MoveObject { public: void Move() { x++; y++; std::cout << "我是NPC\n"; }
NPCObject* Move1() { x++; y++; return this; } };
class MonsterObject :public MoveObject { public: void Move() { x++; y++; std::cout << "我是怪物\n"; }
MonsterObject* Move1() { x++; y++; return this; } };
void Move(MoveObject& obj) { obj.Move(); }
int main() { MonsterObject snake; NPCObject zsf; Move(snake); Move(zsf); }
|
虚函数详解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
#include <iostream>
class MoveObject { public: int x; int y;
MoveObject() { std::cout << this << std::endl; this->Move(); } virtual void Move() { std::cout << "MoveObject Moving~\n"; }
void test() { Move(); }
~MoveObject() { Move(); } };
class MonsterObject :public MoveObject { public: void Move() override { std::cout << "Monster Moving\n"; } MonsterObject() { std::cout << this << std::endl; MoveObject::test(); } ~MonsterObject() { Move(); } };
int main() { MonsterObject snake; snake.test(); }
|
调用虚函数基类版本
默认实参在虚函数重点错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| virtual void AutoMove(int step = 2) { std::cout << "auto move" << step << std::endl; }
void AutoMove(int step = 3) override { std::cout << "~~~~~~auto move" << step << std::endl; }
MonsterObject snake;
MoveObject* p = &snake; p->AutoMove();
|
释放含有虚函数的派生对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
#include <iostream>
class MoveObject { public: int x; int y;
MoveObject() { std::cout << this << std::endl; this->Move(); } virtual void Move() { std::cout << "MoveObject Moving~\n"; }
virtual void AutoMove(int step = 2) { std::cout << "auto move" << step << std::endl; }
void test() { Move(); }
virtual ~MoveObject() { std::cout << " Moveobj析构函数!!" << std::endl; Move(); } };
class MonsterObject :public MoveObject { public: void Move() override { std::cout << "Monster Moving\n"; } MonsterObject() { std::cout << this << std::endl; MoveObject::Move(); } void AutoMove(int step = 3) override { std::cout << "~~~~~~auto move" << step << std::endl; } ~MonsterObject() { std::cout << " Monsterobj析构函数!!" << std::endl; Move(); } };
int main() {
MoveObject* p = new MonsterObject(); p->AutoMove(); delete p;
}
|
在类里面,析构函数和构造函数是静态绑定,其余都是动态绑定的。
对象多态详解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
#include <iostream> class MoveObject { public: int x; };
class MonsterObject :public MoveObject {};
class NPCObject :public MoveObject {};
class Wolf :public MonsterObject {};
class Man :public MonsterObject {};
class WolfMan :public Wolf,public MoveObject,public Man {};
int main() { MonsterObject monster; MoveObject* _move = &monster;
MonsterObject* _pmonster = (MonsterObject*)_move; MonsterObject* _pmonsterA = static_cast<MonsterObject*>(_move);
WolfMan wolfman;
void* ptr = &wolfman; Wolf* pwlf = &wolfman; std::cout << "ptr: " << ptr << std::endl; std::cout << "pwlf: " << pwlf << std::endl;
std::cout << "----------------------" << std::endl; void* ptr1 = &wolfman; Wolf* pwlf1 = (Wolf*)ptr1; std::cout << "ptr1: " << ptr1 << std::endl; std::cout << "pwlf1: " << pwlf1 << std::endl;
std::cout << "----------------------" << std::endl; void* ptr2 = &wolfman; Wolf* pwlf2 = (Wolf*)&wolfman; std::cout << "ptr2: " << ptr2 << std::endl; std::cout << "pwlf2: " << pwlf2 << std::endl;
std::cout << "----------------------" << std::endl; WolfMan wolfman1; wolfman1.::Wolf::MonsterObject::MoveObject::x = 2500; wolfman1.::MoveObject::x = 3500; MoveObject* _move1 = static_cast<MoveObject*>(&wolfman1);
std::cout << _move1->x << std::endl; }
|
强制类型转换都是有风险的!!!
动态强制转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
#include <iostream> class MoveObject { public: int x; virtual void test() { } virtual void Move() { } };
class MonsterObject :public MoveObject { public: void Move() {}; };
class NPCObject :public MoveObject { public: void Move() {}; };
class Wolf :public MonsterObject {};
class Man :public MonsterObject {};
class boss {
};
class WolfMan : public Man {};
int main() {
MonsterObject monster; MoveObject* _move =(MoveObject*)&monster; MoveObject& lMove = monster;
WolfMan wlfman; MoveObject* pMove = &wlfman; auto p = dynamic_cast<WolfMan*>(pMove); auto p1 = dynamic_cast<boss*>(pMove);
std::cout << "p: " << p << std::endl; std::cout << "p1: " << p1 << std::endl; }
|
抽象类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include <iostream>
class Animal {
void virtual Move() = 0; void virtual fly() = 0; void virtual Notice() = 0; void virtual Eat() = 0;
protected: Animal() {} };
class Dog :public Animal { void virtual Move() {
} };
class Cat :public Animal { void virtual Move() {
} };
int main() {
}
|
类的成员函数的指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
#include <iostream>
class Wolf; typedef void (Wolf::* PGROUP)();
class Wolf { public: static void Count() {
}
Wolf() { pGroup = &Wolf::Group0; (this->*pGroup)(); }
void Group0() { std::cout << "一阶段!!!" << std::endl; } void Group1() { std::cout << "二阶段!!!" << std::endl; } void Group2() { std::cout << "三阶段!!!" << std::endl; }
PGROUP pGroup; };
typedef void(*COUNT)();
int main() { PGROUP pFunction = &Wolf::Group2; Wolf* pWolf = new Wolf(); (pWolf->*pFunction)();
COUNT _count = &Wolf::Count; _count(); }
|
1 2 3 4
| class Wolf;
typedef void (Wolf::* PGROUP)();
|
1 2 3 4 5 6
| Wolf() { pGroup = &Wolf::Group0; (this->*pGroup)(); PGROUP pGroup; }
|
1 2 3
|
typedef void(*COUNT)();
|
1 2 3 4 5 6 7 8 9 10
| int main() { PGROUP pFunction = &Wolf::Group2; Wolf* pWolf = new Wolf(); (pWolf->*pFunction)();
COUNT _count = &Wolf::Count; _count(); }
|
成员函数指针:指向类成员函数时,需要使用::*语法并制定类名。在调用的时候,必须通过类实例(this指针)来调用。
静态成员函数:静态成员函数不依赖于对象实例,可以像普通函数一样直接通过类名或函数指针调用。
成员函数与普通函数指针的不同:成员函数指针需要对象实例来调用,而普通函数指针则不需要。
多态:虚函数的实现
(面试可能问到)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| #include <iostream> #include <Windows.h>
void Hack() { std::cout << "劫持了!!!1" << std::endl; } class AIM { public: int HP; virtual void Eat() { std::cout << "AIM" << std::endl; } virtual void Die() { std::cout << "AIM_die" << std::endl; } };
class Wolf :public AIM { public: virtual void Eat() { std::cout << "Wolf" << std::endl; }
virtual void Die() { std::cout << "WOLF-DIE" << std::endl; }
void Sound() { std::cout << "aoaoaoaoa~~~~" << std::endl; } };
int main() { AIM* wolf = new Wolf(); wolf->Die(); std::cout << sizeof(AIM) << std::endl;
std::cout << wolf << " " << &wolf->HP << std::endl;
unsigned* vtable = (unsigned*)wolf; std::cout << std::hex << "Vtable: " << vtable[0] << std::endl;
unsigned* func = (unsigned*)vtable[0];
std::cout << std::hex << "eat: " << func[0] << std::endl; std::cout << std::hex << "die: " << func[1] << std::endl; DWORD old; VirtualProtect(func, 8, PAGE_EXECUTE_READWRITE, &old); func[0] = (unsigned)Hack; func[1] = (unsigned)Hack; wolf->Eat();
AIM* _aim = new AIM(); _aim->Eat();
AIM* _aim1 = new Wolf(); _aim1->Eat();
Wolf wl; wl.Sound(); wl.Eat(); }
|
虚表的性质
1️⃣ 同一个类的多个实例都指向同一个虚函数表
2️⃣ 通过修改虚函数表的数据可以实现劫持
3️⃣ 只有通过指针访问函数才会调用虚函数表