虚函数

C++中的虚函数(virtual function)

╄→гoц情女王★ 提交于 2019-12-07 06:56:26
1.简介 虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。假设我们有下面的类层次: class A { public: virtual void foo() { cout << "A::foo() is called" << endl;} }; class B: public A { public: virtual void foo() { cout << "B::foo() is called" << endl;} }; 那么,在使用的时候,我们可以: A * a = new B(); a->foo(); // 在这里,a虽然是指向A的指针,但是被调用的函数(foo)却是B的! 这个例子是虚函数的一个典型应用,通过这个例子,也许你就对虚函数有了一些概念。它虚就虚在所谓“推迟联编”或者“动态联编”上,一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的。由于编写代码的时候并不能确定被调用的是基类的函数还是哪个派生类的函数,所以被成为“虚”函数。 虚函数只能借助于指针或者引用来达到多态的效果,如果是下面这样的代码,则虽然是虚函数,但它不是多态的: class A { public: virtual void foo(); }; class B: public A { virtual void foo(); };

c++的虚析构函数和纯虚析构函数

泄露秘密 提交于 2019-12-07 06:56:12
虚函数是用作实现子类的多态性的,它可以在运行的过程中选择子类或者父类的同名函数,意思就是说,每次只有一个函数运行。 但是对于析构函数来说,子类 与父类在销毁对象时,都应该要调用 ,所以把父类的析构函数定义为虚函数,会发生什么事情呢。 class { public: A(){cout<<"A constructor"<<endl;} virtual ~A(){count<<"A delete"<<endl;} }; class B:public A { public B(){cout<<"B constructor"<<endl;} public ~B(){cout<<"B delete"<<endl;} }; int main() { A *p = new B(); return 0; } 可以发现,A 和 B都调用了析构函数,这时如果把A类的virtual 去掉,那么就不会调用B的析构函数了。 为什么呢?因为父类只能调用子类中继承父类的方法,而如果需要父类调用以属于子类实现的方法,那么只有把父类中同名的方法设置成虚函数,所以把父类的析构函数设置为虚函数,父类才能调用子类的析构函数。 所以把基类的析构函数写为虚函数与其它成员函数写作虚函数是不一样的。 还有一个问题就是为什么不能把构造函数设置成虚函数? 1.因为虚函数是用来实现多态,如果把基类的构造函数设置成虚函数后

C++纯虚函数

不问归期 提交于 2019-12-07 06:55:29
在成员函数的形参后面写上=0,则成员函数为纯虚函数。 纯虚函数声明: virtual 函数类型 函数名 (参数表列) = 0; class Person { virtual void Display () = 0 ; // 纯虚函数 protected : string _name ; // 姓名 }; class Student : public Person {}; 注意: (1)纯虚函数没有函数体; (2)最后面的“=0”并不表示函数返回值为0,它只起形式上的作用,告诉编译系统“这是虚函数”; (3)这是一个声明语句,最后有分号。 纯虚函数只有函数的名字而不具备函数的功能,不能被调用。 纯虚函数的作用是在基类中为其派生类保留一个函数的名字,以便派生类根据需要对他进行定义。如果在基类中没有保留函数名字,则无法实现多态性。 如果在一个类中声明了纯虚函数,在其派生类中没有对其函数进行定义,则该虚函数在派生类中仍然为纯虚函数。 抽象类: 不用定义对象而只作为一种基本类型用作继承的类叫做抽象类(也叫接口类),凡是包含纯虚函数的类都是抽象类,抽象类的作用是作为一个类族的共同基类,为一个类族提供公共接口,抽象类不能实例化出对象。 纯虚函数在派生类中重新定义以后,派生类才能实例化出对象。 总结: 1、派生类重写基类的虚函数实现多态,要求函数名、参数列表、返回值完全相同。(协变除外) 2

C++系列(纯虚函数和抽象类)

天大地大妈咪最大 提交于 2019-12-07 06:54:33
下面通过一个例子来说明纯虚函数的定义方法 在这个类当中,我们定义了一个普通的虚函数,并且也定义了一个纯虚函数。那么,纯虚函数是什么呢??从上面的定义可以看到, 纯虚函数就是没有函数体,同时在定义的时候,其函数名后面要加上“= 0” 。 纯虚函数的实现原理 本节从虚函数表的角度来说明纯虚函数的实现原理。 上面就是我们在前面课程讲到的多态的实现原理,在讲这一部分的时候,讲到了虚函数表以及虚函数表指针。如果我们定义了Shape这样的类,那么,Shape类当中,因为有虚函数和纯虚函数,所以,它一定有一个虚函数表,当然,也就一定有一个虚函数表指针。如果是一个普通的虚函数,那么,在虚函数表中,其函数指针就是一个有意义的值;如果是一个纯虚函数,那么,在虚函数表中,其函数指针的值就是0。也就是说,在虚函数表当中,如果是纯虚函数,那么就实实在在的写上0,如果是普通的虚函数,那就肯定是一个有意义的值。通过对纯虚函数的讲解,大家也一定会发现:纯虚函数也一定是某个类的成员函数,那么,包含纯虚函数的类也叫作什么呢? 我们把包含纯虚函数的类称之为抽象类 。比如刚刚举的Shape类当中就含有一个计算周长的纯虚函数,那么,我们就说这个Shape类是一个抽象类。大家可以想一想,如果我们使用Shape这个类去实例化一个对象,那么这个对象实例化之后,如果想要去调用纯虚函数(比如要去调用这个计算周长的纯虚函数)

C++中虚析构函数的作用

断了今生、忘了曾经 提交于 2019-12-07 06:54:24
我们知道,用C++开发的时候,用来做基类的类的析构函数一般都是虚函数。可是,为什么要这样做呢?下面用一个小例子来说明: 有下面的两个类: class ClxBase { public : ClxBase() {}; virtual ~ ClxBase() {}; virtual void DoSomething() { cout << " Do something in class ClxBase! " << endl; }; }; class ClxDerived : public ClxBase { public : ClxDerived() {}; ~ ClxDerived() { cout << " Output from the destructor of class ClxDerived! " << endl; }; void DoSomething() { cout << " Do something in class ClxDerived! " << endl; }; }; 代码 ClxBase * pTest = new ClxDerived; pTest -> DoSomething(); delete pTest; 的输出结果是: Do something in class ClxDerived! Output from the destructor of

基类的纯虚析构函数一定要予以实现

穿精又带淫゛_ 提交于 2019-12-07 06:51:19
Effective C++ 条歀07:为多态基类声明virtual析构函数(Declare destructors virtual in polymorphic base classes) 纯虚函数 纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。 虚函数是C++语言的精髓。含有纯虚函数的类被称为抽象类,不能被实例化生成对象,只能派生。由它派生的类的纯虚函数如果没有被实现,那么,该派生类还是个抽象类。 只有全部实现了纯虚函数的派生类才可以被实例化。 纯虚函数的可定义性 定义一个函数为纯虚函数,一般表示该函数没有被实现。但是,这不代表纯虚函数不能被实现。 纯虚函数也是可以定义的 。 纯虚析构函数 虚析构函数是为了让通过基类指针或引用可以正确释放派生类对象。有时候如果想让基类成为一个抽象类,也就是不能被实例化,可以为类引入一个纯虚函数。但如果手上没有任何pure virtual函数时,该怎么办?由于抽象类总是会被作为基类用于派生的,而基类就该有一个虚的析构函数,并且由纯虚函数可以导致抽象类。所以常常把基类的析构函数声明为纯虚析构函数。又由于所有对象析构时,最后都会调用其基类的析构函数,所以 基类的析构函数必须有定义 。纯虚析构函数也不例外。 所以,

快速上手Gobject

百般思念 提交于 2019-12-06 14:54:11
What is G-object? — 很多人被灌输了这样一种概念:要写面向对象程序,那么就需要学习一种面向对象编程语言,例如C++、Java、C#等等,而C语言是用来编写结构化程序的。 — 事实上,面向对象只是一种编程思想,不是一种编程语言。换句话说,面向对象是一种游戏规则,它不是游戏。 — Gobject,亦称Glib对象系统,是一个程序库,它可以帮助我们使用C语言编写面向对象程序;它提供了一个通用的动态类型系统(GType)、一个基本类型的实现集(如整型、枚举等)、一个基本对象类型-Gobject、一个信号系统以及一个可扩展的参数/变量体系。 Why Bother to use Gobject ? — GObject告诉我们,使用C语言编写程序时,可以运用面向对象这种编程思想。 — Gobject系统提供了一个灵活的、可扩展的、并且容易映射到其他语言的面向对象的C语言框架。 — GObject的动态类型系统允许程序在运行时进行类型注册,它的最主要目的有两个: 1)使用面向对象的设计方法来编程。GObject仅依赖于 GLib 和 libc ,通过它可使用纯C语言设计一整套面向对象的软件模块。 2)多语言交互。在为已经使用 GObject框架写好的函数库建立多语言连结时,可以很容易对应到许多语言,包括C++、Java、Ruby、Python和.NET/Mono等

纯虚函数

早过忘川 提交于 2019-12-06 10:55:52
1 #include<iostream> 2 using namespace std; 3 class shape{//图形类 4 public: 5 virtual double area() = 0;//纯虚函数 6 }; 7 class rect:public shape{ 8 int ma; 9 int mb; 10 public: 11 rect(int a,int b){//构造函数 12 ma = a; 13 mb = b; 14 } 15 double area(){ 16 return ma*mb; 17 } 18 }; 19 class circle:public shape{ 20 int mr; 21 public: 22 circle(int r){ 23 mr = r; 24 } 25 double area(){ 26 return 3.14*mr*mr; 27 } 28 }; 29 void area(shape*p){//纯虚函数抽象类不能定义对象,抽象类能够定义指针 30 //该指针指向抽象类的子类,抽象类的子类肯定会把纯虚函数实现了 31 //通过抽象类的指针调用纯虚函数的语句是编译运行过的 32 double r = p->area(); 33 cout << "r=" << r << endl; 34 } rect r(4,4)=16

c++——《我的第一本c++书》

跟風遠走 提交于 2019-12-06 08:44:53
函数 优秀函数的五个要点 函数的返回值:直接返回和间接返回(指针) 在函数的入口处对参数有效性进行检验:if语句,断言(assert) 如果函数有返回值,不可返回一个指向函数体内局部对象的指针或引用 函数的功能要单一 面向对象 60年代软件危机:在软硬件系统逐渐复杂的情况下,软件如何得到良好的设计和维护 结构化程序设计方法(60-80年代):提出问题,把一个大问题划分为几个小问题,即各个子模块,解决每个子模块,最后通过主函数按照某种次序调用子模块(自顶向下、逐步求精) 优点: 程序仅由三种基本结构组成:顺序、选择、循环 分而治之、各个击破 自顶向下、逐步求精 缺点: 数据和操作相互分离:如果数据的格式发生变化,相应的操作函数就要重写 难以扩展:扩展功能涉及模块的重新划分,需大量改写原来函数 难以复用:模块与具体应用环境结合紧密,旧有的模块难以在新程序中复用 面向对象程序设计方法:现实世界是由许多彼此相关并互通信息的实体——对象(object)组成,而每个对象都由两部分组成,描述对象属性的数据和描述对象行为的函数(方法)。数据和函数紧密结合共同构成对象描述现实世界 特点: 封装:对象使数据和操作紧密结合 继承:支持代码复用 多态:使得不同结构的对象可以共享相同的外部接口 优点 容易设计、维护:代码符合认识规律,易于理解,可读性高 复用设计和代码,系统质量高:继承和多态 容易扩展

多态的C语言实现版本

放肆的年华 提交于 2019-12-06 07:03:11
1 #ifndef _51_2_H 2 #define _51_2_H 3 typedef void Demo; 4 typedef void Derived; 5 Demo* Demo_create(int i,int j); 6 int Demo_geti(Demo*pthis); 7 int Demo_getj(Demo*pthis); 8 int Demo_add(Demo*pthis,int value); 9 void Demo_free(Demo*pthis); 10 11 Derived*Derived_create(int i,int j,int k); 12 int Derived_getk(Derived*pthis); 13 int Derived_add(Derived*pthis,int value); 14 #endif 1 #include<stdio.h> 2 #include"51-2.h" 3 #include<malloc.h> 4 //定义父子类的虚函数 5 static int Demo_virtual_add(Demo*pthis,int value); 6 static int Derived_virtual_add(Derived*pthis,int value); 7 //2。确定虚函数表的类型,虚函数表的结构体,用来创建虚函数表