【C++】多态总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dream_1996/article/details/78010115

多态

多态是如何实现绑定的?

多态绑定分两种情况,一种是静态绑定即编译时多态,一种是动态绑定即运行时多态

  • 编译时多态:

是利用重载实现的。对于非虚函数的成员来说,系统在编译时,按照函数的参数的区别来绑定要实现的操作,在编译时就确定了调用哪个函数。

  • 运行时多态:

简单地说,虚函数是动态绑定的基础;动态绑定是实现运行时多态的基础。 要触发动态绑定,需满足两个条件: (1) 只有虚函数才能进行动态绑定,非虚函数不进行动态绑定。
(2) 必须通过基类类型的引用或指针进行函数调用。 通过基类指针或基类引用做形参,当实参传入不同的派生类(或基类)的指针或引用,在函数内部触发动态绑定,从而来运行时实现多态的。

所以说,为什么调用普通函数比调用虚函数的效率高?

因为普通函数是静态联编的,而调用虚函数是动态联编的。

  • 静态联编 :在编译的时候就确定了函数的地址,然后call就调用了。
  • 动态联编 : 首先需要取到对象的首地址,然后再解引用取到虚函数表的首地址后,再加上偏移量才能找到要调的虚函数,然后call调用。

明显动态联编要比静态联编做的操作多,肯定就费时间。

为什么要用虚函数表(存函数指针的数组)?

  • 实现多态,父类对象的指针指向父类对象调用的是父类的虚函数,指向子类调用的是子类的虚函数。
  • 同一个类的多个对象的虚函数表是同一个,所以这样就可以节省空间,一个类自己的虚函数和继承的虚函数还有重写父类的虚函数都会存在自己的虚函数表。

多继承的虚函数对象模型

参见此博客:http://blog.csdn.net/dream_1996/article/details/70176600

为什么要把基类的析构函数定义为虚函数?

在用基类操作派生类时,为了防止执行基类的析构函数,不执行派生类的析构函数。因为这样的删除只能够删除基类对象, 而不能删除子类对象, 形成了删除一半形象, 会造成内存泄漏.

为什么要把基类的析构函数定义为虚函数就可以调用子类析构函数呢?看下面代码

#include<iostream>
using namespace std;

class Base
{
public:
	Base() {};
	~Base() 
	{
		cout << "delete Base" << endl;
	};
};

class Derived : public Base
{
public:
	Derived() {};
	~Derived()
	{
		cout << "delete Derived" << endl;

	};
};
int main()
{
	//操作1
	Base* p1 = new Derived;
	delete p1;
	//因为这里子类的析构函数重写了父类的析构函数,虽然子类和父类的析构函数名不一样,
	//但是编译器对析构函数做了特殊的处理,在内部子类和父类的析构函数名是一样的。
	//所以如果不把父类的析构函数定义成虚函数,就不构成多态,由于父类的析构函数隐藏了子类
	//的析构函数,所以只能调到父类的析构函数。
	//但是若把父类的析构函数定义成虚函数,那么调用时就会直接调用子类的析构函数,
	//由于子类析构先要去析构父类,在析构子类,这样就把子类和继承的父类都析构了

	system("pause");
}


为什么子类和父类的函数名不一样,还可以构成重写呢?

因为编译器对析构函数的名字做了特殊处理,在内部函数名是一样的。

抽象类

抽象类是利用虚函数的延伸

virtual void Display() = 0;//存虚函数

含有存虚函数的类为抽象类,也叫接口类,不能实例出对象

抽象类应用

抽象类就是用来继承的,如多个子类继承同一个抽象类,就都可以重写这个共同父类的存虚函数,这样的话我们用父类的指针来接收子类,我们把哪个子类传给父类,就调用的是那个子类里的方法,是不是很方便,抽象类也是一种规范化的编程。

C++ static

  • 类的静态成员是属于这个类的,属于类的每一个对象
  • 基类的静态成员,不管这个基类派生出多少子类,只有这么一个静态成员。
  • 我们在使用时要注意:

(1)静态方法只能访问类的静态成员,不能访问类的非静态成员;
(2)非静态方法可以访问类的静态成员,也可以访问类的非静态成员;
(3)静态方法既可以用实例来调用,也可以用类名来调用。

c 中 static

  • 修饰全局变量,改变变量的连接属性,不能其他文件调用,不改变存储属性。
  • 修饰局部变量,改变存储属性,变为存储带静态全局区,不改变连接属性,因为它属于局部变量。

猜你喜欢

转载自blog.csdn.net/dream_1996/article/details/78010115