问题引出
如果子类定义了与父类中原型相同的函数会发生什么?
#include <cstdlib>
#include <iostream>
using namespace std;
class Parent
{
public:
Parent(int a)
{
this->a = a;
cout << "Parent a " << a << endl;
}
void print()
{
cout << "Parent 打印 " << a << endl;
}
private:
int a;
};
class Child : public Parent
{
public:
Child(int b) : Parent(10)
{
this->b = b;
cout << "Child b " << b << endl;
}
void print()
{
cout << "Child 打印 " << b << endl;
}
private:
int b;
};
void howToPrint(Parent *base)
{
base->print();
}
void howToPrint2(Parent &base)
{
base.print();
}
//面向对象新需求 如果传子类对象就执行子类的函数,如果传父类对象就执行父类的函数
void main()
{
Parent *base = NULL;
Parent p1(20);
Child c1(30);
//案例一
base = &p1; //调用父类Parent的print函数打印
base->print();
base = &c1;
base->print(); //请问执行的是谁的函数 答案:执行的是父类的函数 但在实际运用中我们更希望它执行子类的,因为是用子类赋值给指针的
{//案例二
Parent &base2 = p1;
base2.print();
Parent &base3 = c1; //base3是c1的别名,但是执行的还是父类的函数,也就是说这里的别名无效了
base3.print();
}
//案例三
{
howToPrint(&p1);
howToPrint(&c1);
howToPrint2(p1);
howToPrint2(c1);
//发现无论传父类对象还是子类对象执行的全是父类的函数,这就和我们期望的不同了
}
system("pause");
}
面向对象新需求
编译器的做法不是我们期望的
根据实际的对象类型来判断重写函数的调用
如果父类指针指向的是父类对象则调用父类中定义的函数
如果父类指针指向的是子类对象则调用子类中定义的重写函数
解决方案
C++中通过virtual关键字对多态进行支持
使用virtual声明的函数被重写后即可展现多态特性
使用多态修改案例
#include <cstdlib>
#include <iostream>
using namespace std;
class Parent
{
public:
Parent(int a)
{
this->a = a;
cout << "Parent a " << a << endl;
}
/* 使用多态 父类写virtual关键字 子类可写可不写,一般都写上 */
virtual void print()
{
cout << "Parent 打印 " << a << endl;
}
private:
int a;
};
class Child : public Parent
{
public:
Child(int b) : Parent(10)
{
this->b = b;
cout << "Child b " << b << endl;
}
virtual void print()
{
cout << "Child 打印 " << b << endl;
}
private:
int b;
};
void howToPrint(Parent *base)
{
base->print();//使用多态实现一个调用语句,有多种表现形态
}
void howToPrint2(Parent &base)
{
base.print();
}
//面向对象新需求 如果传子类对象就执行子类的函数,如果传父类对象就执行父类的函数
void main()
{
Parent *base = NULL;
Parent p1(20);
Child c1(30);
//案例一
base = &p1; //调用父类Parent的print函数打印
base->print();
base = &c1;
base->print(); //请问执行的是谁的函数 答案:执行的是父类的函数 但在实际运用中我们更希望它执行子类的,因为是用子类赋值给指针的
{//案例二
Parent &base2 = p1;
base2.print();
Parent &base3 = c1; //base3是c1的别名,但是执行的还是父类的函数,也就是说这里的别名无效了
base3.print();
}
//案例三
{
howToPrint(&p1);
howToPrint(&c1);
howToPrint2(p1);
howToPrint2(c1);
//发现无论传父类对象还是子类对象执行的全是父类的函数,这就和我们期望的不同了
}
system("pause");
}
使用多态后,下面的结果符合我们的主观需求