在学习多态之前我们首先要回顾一下继承中的隐藏函数的概念
多态就是不同的对象在左同一件事的时候,结果不同
(不同的对象在调用一个函数的时候,他们分别会去调用自己类的那个同名函数)
例如:购买火车票,普通人和学生的价格是不同的,但是他们都执行了买票这一动作,产生的车票是不同的
像这样让两个对象:ps st 都调用fun()函数的时候,结果发生了不同。就是多态。使得两个对象乐意产生多态的两个虚函数,就是函数的重写。
函数的重写:只存在类的继承关系中,重写函数前面要加virtual 使得函数变为虚函数,如果不加的话两个函数就变成影藏函数关系了
且两个重写函数中不一定都要在前面都写virtual 只在父类中写,基类中不写也是可以构成函数重写的
区分函数重载,重写,隐藏
如果是用父类的引用或者指针去接收对象,在调用的话就是多态调用,如果直接用创建的对象去调用的话就是构成隐藏
重载:
class Person {
public:
virtual void BuyTicket() { cout << "买票-全价" << endl; }
};
class Student : public Person {
public:
virtual void BuyTicket() { cout << "买票-半价" << endl; }
};
int main()
{
Person ps;
Student st;
Person& p = ps;
Person& pp = st;
p.BuyTicket(); //买票 - 全价
pp.BuyTicket(); //买票 - 半价
cout << "//" << endl;
Person* p1 = new Person;
Person* p2 = new Student;
p1->BuyTicket();//买票-全价
p2->BuyTicket();//买票-半价
return 0;
}
隐藏:
class Person {
public:
virtual void BuyTicket() { cout << "买票-全价" << endl; }
};
class Student : public Person {
public:
virtual void BuyTicket() { cout << "买票-半价" << endl; }
};
int main()
{
Student st;
st.BuyTicket();//买票-半价
st.Person::BuyTicket();//买票-全价
return 0;
}
综合难题:下边这段代码的打印结果?
class A
{
public:
virtual void fun(int val = 1)
{
cout << "A->" << val << endl;
}
virtual void test() { fun(); }
};
class B:public A
{
public:
void fun(int val = 0)
{
cout << "B->" << val << endl;
}
};
int main()
{
B* p = new B;
p->test();
return 0;
}
之前的继承中说道想要类不能被继承,在类名后加关键字final
——想要virtual修饰出的虚函数不能被重写,那么也可以就在这个虚函数后面加final
在类中存在虚函数的内存对齐,多态的底层原理
在32位机器上,求下面这段代码输出的b的大小
class Base
{
public:
virtual void fun1()
{
cout << "Base::fun1()" << endl;
}
virtual void fun2()
{
}
protected:
int _a;
char _ch;
};
int main()
{
Base b;
cout << sizeof(b)<<endl;
}
之前我们学过求类的大小就是求类里面的变量的大小然后结构体内存对齐的大小
那么此题是不是就是求出比变量内存后的大小呢?
变量内存对齐
但是当我们输出测试大小的时候显示的是12,这是为什么呢?
原因是,如果类中存在虚函数(不管是一个还是多个)那么就存在一个虚函数指针,且次指针计入类的大小,既然是指针那么他的大小在32位机器上大小为4
所以类的大小应该为12:
那么这个虚函数指针又是用来干什么的呢
虚函数指针指向的虚函数指针数组(虚表)里面指向的是类里面的虚函数的各自的地址 虚函数数组存在常量区