C++之多态与继承学习笔记

来源:互联网 发布:公安打击网络犯罪 编辑:程序博客网 时间:2024/06/06 07:01

如果子类定义了与父类中原型相同的函数会发生什么?

例如

class Parent

{

public:

   void print()

    {

       cout<<"I'm Parent..."<<endl;

    }

};

 

class Child : public Parent

{

public:

   void print()

    {

       cout<<"I'm Child..."<<endl;

    }

};

使用时

Child child;

child.print();

child.Parent::print();

 

父类中被重写的函数依然会继承给子类默认情况下子类中重写的函数将隐藏父类中的函数通过作用域分辨符::可以访问到父类中被隐藏的函数

使用子类变量给父类指针赋值和引用赋值时

Childchild;

Parent *PP = &child;

Parent &rP = child;

Child.print();//Iam child

PP->print();//Iam parent

rP.print();//Iam parent

C++与C相同,是静态编译型语言

在编译时,编译器自动根据指针的类型判断指向的是一个什么样的对象。所以编译器认为父类指针指向的是父类对象(根据赋值兼容性原则,这个假设合理),由于程序没有运行,所以不可能知道父类指针指向的具体是父类对象还是子类对象从程序安全的角度,编译器假设父类指针只指向父类对象,因此编译的结果为调用父类的成员函数。

 

面向对象的新需求:据实际的对象类型来判断重写函数的调用,父类指针指向的是父类对象则调用父类中定义的函数,父类指针指向的是子类对象则调用子类中定义的重写函数。

 

解决的办法就是多态,

 

面向对象中的多态:

根据实际的对象类型决定函数调用语句的具体调用目标。

C++中的多态支持

c++通过virtual关键字对多态进行支持用virtual声明的函数被重写后即可展现多态特性。

父类的重写函数经过virtual声明后,父类指针指向子类后,调用的函数会是子类新定义的,由此实现了多态,据实际的对象类型来判断重写函数的调用,而不是父类指针只能指向父类的函数。

虚函数只有在继承的时候才能体现它的作用。

重写与重载的区别

函数重载:必须在同一个类中进行,子类无法重载父类的函数,父类同名函数将被覆盖,重载是在编译期间根据参数类型和个数决定调用函数。

函数重写:必须发生于父类与子类之间,并且父类与子类中的函数必须有完全相同的原型,使用virtual声明之后能够产生多态,多态是在运行期间根据具体对象的类型决定调用函数。

 

是否可以将类的每个成员函数都声明为虚函数?

C++中多态的实现原理:当类中声明虚函数时,编译器会在类中生成一个虚函数表,

虚函数表是一个存储类成员函数指针的数据结构,虚函数表是由编译器自动生成与维护的

virtual成员函数会被编译器放入虚函数表中,存在虚函数时,每个对象中都有一个指向虚函数表的指针。

通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数。而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。出于效率考虑,没有必要将所有成员函数都声明为虚函数。

 

对象中的VPTR指针什么时候被初始化?

对象在创建的时候由编译器对VPTR指针进行初始化

只有当对象的构造完全结束后VPTR的指向才最终确定

父类对象的VPTR指向父类虚函数表

子类对象的VPTR指向子类虚函数表

结论:构造函数中调用虚函数无法实现多态。

 

纯虚函数的使用:c++中使用纯虚函数可以构造抽象类。

面向对象中的抽象类:抽象类可用于表示现实世界中的抽象概念, 抽象类是一种只能定义类型,而不能产生对象的类,抽象类只能被继承并重写相关函数。

抽象类的直接特征是纯虚函数,抽象类不能用于定义对象,抽象类只能用于定义指针和引用,抽象类的纯虚函数必须被子类重写,抽象类的标志就是纯虚函数。

0 0
原创粉丝点击