C++虚函数和纯虚函数的区别
2017-08-01 16:15
253 查看
C++里,有虚函数也有纯虚函数,这两个概念名字很像,但是作用却不同,下面讲一下这两个概念的区别。
我们先来看一看不用虚函数的情况:
这样的话,我们要实现多态,就需要使用虚函数了,将上面的代码稍微改动一下。只需要在基类的hello()方法里前添加关键字virtual就行了。
可以看到,通过虚函数,我们实现了多态。那么虚函数的大致工作原理是什么呢?
一一一一一一一
Base
一一一一一一一
Derived
一一一一一一一
Base部分和Derived部分是连接在一起的。两个一起组成了子类对象。
每一个类都有一个虚函数表(v-table),每个对象都有一个虚函数指针(vptr),指向虚函数表。当子类对象被创建后,虚函数指针就会指向子类中覆盖的虚函数。当使用基类指针时,虚函数指针将根据基类指针指向的对象的实际类型,来指向正确的函数。
当然,这个只是大概的步骤,虚函数在每本C++书里都会有介绍,如果想要更详细,深入的了解虚函数,可以去看看一些C++的经典著作。
virtual void hello() = 0;
假如我们有一个Person类,这个类的所有对象要有一个呼吸的动作,我们声明了一个抽象类IBreath,里面有一个纯虚函数breath(),之后通过Person继承了这个抽象类,强制实现了breath()函数。
虚函数
虚函数主要是用在多态方面。虚函数是在基类中声明函数为virtual,并在子类中重写的函数,虚函数可以通过基类类型的指针调用子类里被重写的虚函数,可以实现多态。我们先来看一看不用虚函数的情况:
子类函数屏蔽基类函数
#include <iostream> using namespace std; class Base { public: void hello() { cout << "hello world Base" << endl; } }; class Derived : public Base { public: void hello() { cout << "hello world Derived" <<endl; } }; int main() { Base b; Derived d; b.hello(); d.hello(); /******* 运行结果 hello world Base hello world Derived ********/ Base *b1; Base *b2; b1 = &b; b2 = &d; b1->hello(); b2->hello(); /******* 运行结果 hello world Base hello world Base ********/ }
使用虚函数实现多态
可以看到,虽然把子类类型的值赋给了基类类型指针b2,但是b2->hello()这代码的结果仍然是调用了基类的hello()方法,这是因为,基类指针只能访问对象的基类部分,所以无法调用子类里的hello方法。这样的话,我们要实现多态,就需要使用虚函数了,将上面的代码稍微改动一下。只需要在基类的hello()方法里前添加关键字virtual就行了。
#include <iostream> using namespace std; class Base { public: void hello() { cout << "hello world Base" << endl; } }; class Derived : public Base { public: virtual void hello() { cout << "hello world Derived" <<endl; } }; int main() { Base b; Derived d; b.hello(); d.hello(); /******* 运行结果 hello world Base hello world Derived ********/ Base *b1; Base *b2; b1 = &b; b2 = &d; b1->hello(); b2->hello(); /******* 运行结果 hello world Base hello world Derived ********/ }
可以看到,通过虚函数,我们实现了多态。那么虚函数的大致工作原理是什么呢?
虚函数工作原理
先说明下,创建派生类的时候,先调用基类的构造函数,再调用子类的构造函数,一个派生类在内存中大概是这样的:一一一一一一一
Base
一一一一一一一
Derived
一一一一一一一
Base部分和Derived部分是连接在一起的。两个一起组成了子类对象。
每一个类都有一个虚函数表(v-table),每个对象都有一个虚函数指针(vptr),指向虚函数表。当子类对象被创建后,虚函数指针就会指向子类中覆盖的虚函数。当使用基类指针时,虚函数指针将根据基类指针指向的对象的实际类型,来指向正确的函数。
当然,这个只是大概的步骤,虚函数在每本C++书里都会有介绍,如果想要更详细,深入的了解虚函数,可以去看看一些C++的经典著作。
纯虚函数
定义
纯虚函数是一种特殊的虚函数,它在基类中声明,却只能在派生类中给实现。在基类中声明纯虚函数的语法为:virtual void hello() = 0;
引入原因
因为C++没有接口这个关键字,我们想要规定一个类的行为的时候,就需要使用纯虚函数来解决问题,因为虚函数没有要求子类强制重写基类的方法,所以说无法靠虚函数规定子类的行为。而纯虚函数可以要求子类强制重写基类的纯虚方法。含有一个或者多个纯虚函数的类称为抽象类,抽象类无法被实例化。代码
class IBreath { public: virtual void breath() = 0; }; class Person : public IBreath { public: void breath() { cout << "breathing...... " << endl; } }; int main() { Person p; p.breath(); // 运行结果:breathing...... }
假如我们有一个Person类,这个类的所有对象要有一个呼吸的动作,我们声明了一个抽象类IBreath,里面有一个纯虚函数breath(),之后通过Person继承了这个抽象类,强制实现了breath()函数。
总结
可以看出,虚函数可以让子类继承并重写方法,但是没有强制的要求,而纯虚函数强制子类重写该函数,所以,纯虚函数总被当成接口来使用,而虚函数可以在实现多态的时候使用。相关文章推荐
- 虚函数、纯虚函数在C++和java中的区别
- 探讨虚函数与纯虚函数的区别
- C++学习 虚函数和纯虚函数的区别
- 纯虚函数虚函数的区别
- 虚函数和纯虚函数的区别
- C++ 虚函数和纯虚函数的区别
- C++ 虚函数和纯虚函数的区别
- C++虚函数与纯虚函数用法与区别
- 虚函数和纯虚函数的区别
- 虚函数和纯虚函数的作用与区别
- 虚函数、纯虚函数、普通函数的区别
- 虚函数和纯虚函数区别
- c++ 虚函数和纯虚函数的区别
- 虚函数与纯虚函数区别
- 虚函数和纯虚函数的区别
- C++虚函数和纯虚函数区别
- 虚函数和纯虚函数的作用与区别!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
- C++中的虚函数、纯虚函数区别和联系
- 虚函数和纯虚函数的区别
- C++虚函数与纯虚函数的区别