目录
多态:一种接口,多种形态
静态多态:如果函数的调用,在编译阶段就可以确定函数的调用地址,并产生代码,就是静态多态(编译时多态)
动态多态:调用地址不能编译不能在编译期间确定,而需要在运行时才能决定,这这就属于晚绑定(动态多态,运行时多态)
发生多态的四个条件:
父类中有虚函数
必须发生继承
子类必须重写虚函数(函数名 参数 返回值一致 函数的内容可以不一致)
父类的指针或引用指向子类的对象
- #include
-
- using namespace std;
-
- class Animal
- {
- public:
- virtual void speak()
- {
- cout << "动物在说话" << endl;
- }
- };
- class Dog:virtual public Animal
- {
- public:
- //重写虚函数 函数的返回值 参数 函数名一样
- void speak()
- {
- cout << "狗在说话" << endl;
- }
- };
- class Cat:virtual public Animal
- {
- public:
- //重写虚函数 函数的返回值 参数 函数名一样
- void speak()
- {
- cout << "猫在说话" << endl;
- }
- };
- //如果两个类发生了继承 父类和子类编译器都会自动转换 不需要人为转换
- void do_work(Animal &obj)//多态接口 一个函数实现不同功能
- {
- obj.speak();//地址早绑定->加上函数前面加上virtual 地址晚绑定
- }
-
- void test01()
- {
- Animal p1;
- do_work(p1);//动物
-
- Dog p2;
- do_work(p2);//狗
-
- Cat p3;
- do_work(p3);//猫
- }
-
- int main()
- {
- test01();
- return 0;
- }
- #include
- using namespace std;
-
- class Calc
- {
- public:
- virtual int mycalc(int a,int b)
- {
- return 0;
- }
- };
-
- class Add:public Calc
- {
- public:
- int mycalc(int a,int b)
- {
- return a + b;
- }
-
- };
- class Mul:public Calc
- {
- public:
- int mycalc(int a,int b)
- {
- return a * b;
- }
-
- };
- class Sub:public Calc
- {
- public:
- int mycalc(int a,int b)
- {
- return a - b;
- }
-
- };
-
- int do_calc(int a,int b,Calc &obj)
- {
- return obj.mycalc(a,b);
- }
-
- void test01()
- {
- Add p1;
- cout << do_calc(3,4,p1) << endl;
-
- Mul p2;
- cout << do_calc(3,4,p2) << endl;
-
- Sub p3;
- cout << do_calc(3,4,p3) << endl;
-
- }
-
- int main()
- {
- test01();
- return 0;
- }
-
为什么可以根据传入对象的不同来执行不同的语句?

纯虚函数:将虚函数等于0 实质是将虚函数 表的函数入口设为NULL
抽象类:一个类如果有纯虚函数,那么这个类就是一个抽象类,抽象类不能实例化对象
继承抽象类的子类也是一个抽象类,如果子类重写了虚函数,那么子类就不是抽象类
- class Calc
- {
- public:
- virtual int mycalc(int a,int b) = 0;//虚函数等于0 纯虚函数
- };
-
- class Mob:public Calc
- {
- public:
- //子类继承了抽象类 子类也是抽象类
- //如果子类重写虚函数 就不是抽象类
- };
-
- //如果有纯虚函数的类 叫做抽象类 抽象类无法实例化对象
- void test()
- {
- //Cacl p;//错误
- Mod p1;
- }
在调用基类的析构函数之前,先调用子类的析构函数
- #include
-
- using namespace std;
-
- class Animal
- {
- public:
- virtual void speak()
- {
- cout << "动物在说话" << endl;
- }
- virtual ~Animal()
- {
- cout << "动物的析构" << endl;
- }
- };
- class Dog:virtual public Animal
- {
- public:
- //重写虚函数 函数的返回值 参数 函数名一样
- void speak()
- {
- cout << "狗在说话" << endl;
- }
- ~Dog()
- {
- cout << "狗的析构" << endl;
- }
- };
- class Cat:virtual public Animal
- {
- public:
- //重写虚函数 函数的返回值 参数 函数名一样
- void speak()
- {
- cout << "猫在说话" << endl;
- }
- };
- //如果两个类发生了继承 父类和子类编译器都会自动转换 不需要人为转换
- void do_work(Animal &obj)//多态接口 一个函数实现不同功能
- {
- obj.speak();//地址早绑定->加上函数前面加上virtual 地址晚绑定
- }
-
- void test01()
- {
- Animal *p = new Dog;
- p->speak();//调用狗的speak
- delete p;//加virtual 调用动物的析构 加virtual之后先调用狗的析构 再调用动物的析构
- }
-
- int main()
- {
- test01();
- return 0;
- }
虚构函数等于零
class Animal
{
public:
virtual void speak()
{
cout << "动物在说话" << endl;
}
virtual ~Animal() = 0;//
};
重载:
函数名相同
同一个作用域
参数的个数、顺序、类型不一致
const也可以成为重载的条件
重定义:
发生继承
子类和父类有同名的变量和函数,父类中同名的变量和函数会被隐藏
重写:
父类中有虚函数
发生了继承
子类重写了虚函数
函数名、返回值、参数一致,函数体不一致