十堰的网站建设,网站无法处理请求,南昌网站建设哪家好薇,百度上做网站模板文章目录 构成多态的条件虚函数作用#xff1a;完成重写 重写重载 重写 隐藏为什么析构函数要搞成符合多态?原理预热对于基类指针或引用指向父类或者子类的成员函数是如何调用不同的函数呢#xff1f; 一个类如果是基类#xff0c;它的析构函数最好加上virtual 构成多态的条… 文章目录 构成多态的条件虚函数作用完成重写 重写重载 重写 隐藏为什么析构函数要搞成符合多态?原理预热对于基类指针或引用指向父类或者子类的成员函数是如何调用不同的函数呢 一个类如果是基类它的析构函数最好加上virtual 构成多态的条件
必须通过基类的指针或者引用调用虚函数被调用的函数必须是虚函数且派生类必须对基类的虚函数进行重写
多态不同对象传递过去调用不同函数 多态调用看的指向的对象 普通对象普通调用不构成多态看当前者类型
虚函数
只有成员函数才可以加virtual 加上virtual它就叫做虚函数
作用完成重写
重写
虚函数重写的一些细节 // 重写的条件本来是虚函数三同即派生类虚函数与基类虚函数的 返回值类型、函数名字、参数列表完全相同但是有一些例外 // 1、派生类的重写虚函数可以不加virtual – 建议大家都加上 // 2、协变返回的值可以不同但是要求返回值必须是父子关系指针和引用
重载 重写 隐藏
函数重载发生在同一作用域
重写和隐藏 发生在基类和派生类 隐藏只要函数名一样就符合条件
为什么析构函数要搞成符合多态?
场景一
class Person
{
public:~Person(){cout ~Person() endl;}
};
class Student:public Person
{
public: ~Student(){cout ~Student() endl;}
};
int main()
{Person ps;Student st;return 0;
}这种情况下程序走的好着呢 也没上多态不是也可以吗为什么非得把父类和子类的析构函数搞成虚函数重写呢 因为下面的场景下不构成重写会造成内存泄漏
class Person
{
public:~Person(){cout ~Person() endl;}
};
class Student:public Person
{
public: ~Student(){cout ~Student() endl;delete[] _a;}
private:int* _a new int[10];
};
int main()
{/*Person ps;Student st;*/Person* p new Person;//基类指针既可以指向基类也可以指向派生类delete p;p new Student; delete p; //p-destructor() operator delete(p)(free) //p是基类指针指向Student,多态条件一满足//这里我们期望p指向谁调用谁的析构//如果析构函数不构成多态那么p-destructor() 是普通调用只看当前者p的类型,永远只调用~personreturn 0;
}运行结果 delete p 做了2件事
p-destructor() operator delete§(free)
如果析构函数不构成多态那么p-destructor() 是普通调用只看当前者p的类型,永远只调用~person
这不是我们期望的这里我们期望p指向谁调用谁的析构
基类指针既可以指向基类也可以指向派生类
那么我们就需要满足多态的条件 p是基类指针指向Student,调用析构函数。多态条件一满足 编译器帮助我们把类析构函数都被处理成destructor这个统一的名字 形参类型一样函数名一样析构又没有返回值那么就需加上virtual即可
class Person
{
public:virtual ~Person(){cout ~Person() endl;}
};
class Student:public Person
{
public: virtual ~Student(){cout ~Student() endl;delete[] _a;}
private:int* _a new int[10];
};
int main()
{/*Person ps;Student st;*/Person* p new Person;//基类指针既可以指向基类也可以指向派生类delete p;p new Student; delete p; //p-destructor() operator delete(p)(free) //p是基类指针指向Student,多态条件一满足//这里我们期望p指向谁调用谁的析构//如果析构函数不构成多态那么p-destructor() 是普通调用只看当前者p的类型,永远只调用~personreturn 0;
}原理
预热
Base的大小是多少呢 那么虚函数存在哪里呢 存在了代码段常量区 回顾我们类和对象大小时的知识成员函数也不保存在对象中而是存放在公共的代码段 这里的vfptr是虚函数表指针存的只是虚函数的地址 成员函数加了virtual就会放到虚函数表指针里面
对于基类指针或引用指向父类或者子类的成员函数是如何调用不同的函数呢
父类指针或者引用指向子类发生切片拿到的仍然是一个父类 指向父类还是父类 那么他们是如何调用不同的成员函数的呢
class Person {
public:virtual void BuyTicket() { cout 买票-全价 endl; }int _a 1;
};class Student : public Person {
public:virtual void BuyTicket() { cout 买票-半价 endl; }int _b 1;
};void Func(Person p)
{// 符合多态运行时到指向对象的虚函数表中找调用函数的地址p.BuyTicket();
}int main()
{Person Mike;Func(Mike);Student Johnson;Func(Johnson);return 0;
}Mike和Johnson的监视中看到他们的虚函数表里面存的地址不同因为子类对父类的虚表进行了覆盖子类拷贝了父类的虚表再进行重写
P指针指向基类和指向子类时调用的函数是不同的地址 符合多态的话P指向父类就是父类P指向子类完成切片后看到的还是一个子类那么P到底是指向父类还是子类就不得而知了。 但是我不管运行时符合多态运行时到指向对象的虚函数表中找调用函数的地址 在编译时就确定成员函数的地址 如果不符合多态那么就看调用者P的类型去Person里去找这个函数在用函数名修饰规则就可以找到函数的地址