C++语言笔记系列之十九——虚函数(2)

1.构造函数和析构函数中调用虚函数

(1)采用静态编译。

(2)在编译阶段自动联接自己类中的函数或基类中的函数,不在派生类中重定义一个函数。

注:构造函数和析构函数中调用的虚函数,派生类都不一定存在的情况下,只能去调用基类或者自身的函数。

example 1

#include <iostream.h>

class A

{

public:

A() {}

virtual void func() {cout<<"A construction."<<endl;}

~A() {}

virtual void fund() {cout<<"Destruction A."<<endl;}

};

class B:public A

{

public:

B() {func();}

void fun() {func();}

~B() {fund();}

};

class C:public B

{

public:

C() {}

void func() {cout<<"C construction."<<endl;}

~C() {fund();}

void fund() {cout<<"C destruction."<<endl;}

};

int main()

{

C c;

c.func();

}

程序输出:

A construction.

C construction.

C destruction.

Destruction A.

2.空虚函数

纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。

(1)表示:

virtual void 函数名() {} //空虚函数

virtual void 函数名()=0; //纯空虚函数

(2)目的:保证类在继承路线上接口唯一。

含义:若派生类想存取虚函数时,必须建立一条从基类到派生类的虚函数路径,许多中间类也必须描述该虚函数以保证其后的派生类可以使用虚函数。

注:类中含有纯虚函数该类就叫做抽象类,不能定义对象。

(3)空虚函数:无函数体,但具有函数形式,空虚函数是可以被调用的。

(4)纯虚函数:

A.没有函数实现过程的虚函数。

B.纯虚函数不可被调用,将纯虚函数的实现留给派生类以实现动态联编完成继承中的多态。

example 2

#include <iostream.h>

class Point

{

int x, y;

public:

Point(int i = 0, int j = 0) {x = i; y = j;}

virtual void set()=0;

virtual void draw()=0;

};

class Line:public Point

{

int x1, y1;

public:

Line(int i = 0, int j = 0, int m = 0, int n = 0):Point(i, j)

{x1 = m; y1 = n;}

void set() {cout<<"Line::set() called."<<endl;}

void draw() {cout<<"Line::draw() called."<<endl;}

};

class Elipes:public Point

{

int x2, y2;

public:

Elipes(int i = 0, int j = 0, int p = 0, int q = 0):Point(i, j)

{x2 = p; y2 = q;}

void set() {cout<<"Elipes::set() called."<<endl;}

void draw() {cout<<"Elipes::draw() called."<<endl;}

};

void drawobj(Point *p)

{p->draw();}

void setobj(Point *p)

{p->set();}

int main()

{

Line *lineobj = new Line;

Elipes *elipesobj = new Elipes;

drawobj(lineobj);

drawobj(elipesobj);

setobj(lineobj);

setobj(elipesobj);

}

程序输出:

Line::draw() called.

Elipes::draw() called.

Line::set() called.

Elipes::set() called.

注:基类Point不是虚基类,系统将会为派生类Line和Elipes分别建立基类副本,在派生类Line、Elipes的构造函数中,都要完整表示对基类构造函数的调用以及参数描述。代码中存在的问题,缺两个delete来释放内存。

3.在基类中定义纯虚函数,不实现其函数功能。

意义:

(1)将基类中set和draw函数的实现放在不同的派生类中去独立实现。

(2)由于纯虚函数是虚函数,只要使基类指针指向派生类对象就可以实现动态联编,就可以调用不同派生类中独立实现的每一个set和draw函数。

4.抽象类

(1)抽象类是一个特殊的类,即含有纯虚函数。

(2)位于继承中的上层——为派生类提供一个统一的界面。

作用:将相关派生类组织在一个继承层次结构中,为子类提供一个公共的根——保证相关子类从同一个根派生而来。

注意:

(1)抽象类只做基类。

(2)不能够创建抽象类的对象。

(3)抽象类的构造函数声明为受保护权限。

(4)不可将抽象类作为函数参数以及函数返回值类型。

(5)可以设置指向抽象类对象的指针,但该指针只可用于指向派生类对象,引用也是如此。

(6)将抽象类中的纯虚函数交给派生类来实现,派生类中也可以不实现,交给派生类的下一级派生类来实现,但是在派生类中必须定义自己的纯虚函数版本。

C++语言笔记系列之十九——虚函数(2)

时间: 2024-10-08 19:34:56

C++语言笔记系列之十九——虚函数(2)的相关文章

C++语言笔记系列之十八——虚函数(1)

1.C++中的多态 (1)多态性:同一个函数的调用可以进行不同的操作,函数重载是实现多态的一种手段. (2)联编:在编译阶段进行联接,即是在编译阶段将一个函数的调用点和函数的定义点联接起来. A.静态联编:在编译阶段就完成的函数联编--函数重载. B.动态联编:在程序的运行阶段由系统自动选择具体的函数--虚函数. 注:C++的多态主要指的就是动态联编. 2.虚函数 (1)虚函数是在函数的定义时将其声明为虚函数即可. (2)说明:virtual 数据类型 函数名(参数表) {函数体} A.目的:当

C++语言笔记系列之十二——C++的继承

C++的继承 1.继承方式 public(公有继承) 派生类中的成员可以访问基类的public成员和protected成员,但不能访问基类的private成员. 派生类的对象只能访问基类的public成员. protected(保护继承),private(私有继承) 派生类中的成员可以访问基类的public成员和protected成员,但不能访问基类的private成员. 派生类的对象不能访问基类的任何成员. 2.例子 example 1: #include <iostream.h> clas

C++语言笔记系列之十六——赋值兼容规则&amp;多继承的二义性

1.赋值兼容规则 (1)派生类对象可以给基类对象赋值,这种情况下派生类对象将从基类继承的成员的值赋值给一个基类对象:但是不允许将一个基类的对象赋值给一个派生类. (2)可以将派生类对象的地址赋给基类指针,使基类指针指向派生类对象,通过基类指针引用成员时只可以引用派生类从基类继承而来的成员,而不允许引用派生类的新成员. (3)引用与指针相同. 2.多继承 (1)一个派生类从两个以上的基类中去继承. (2)说明: class 派生类名:继承方式 基类1, 继承方式 基类2,...... {派生类成员

C++语言笔记系列之十四——继承后的访问权限

1.析构函数不继承:派生类对象在析构时,基类析构函数的调用顺序与构造函数相反. 注:派生类对象建立时要调用基类构造函数,派生类对象删除时要调用基类析构,顺序与构造函数严格相反. 2.例子 example 1 #include <iostream.h> #include <math.h> class Point { public: Point(double a, double b, doule c) { x = a; y = b; z = c; } double Getx() {re

C++语言笔记系列之十五——派生类、基类、子对象的构造和析构函数调用关系

例子 example 1 注:若一个基类同时派生出两个派生类,即两个派生类从同一个基类继承,那么系统将为每一个简历副本,每个派生类独立地使用自己的基类副本(比如基类中有属于自己类的静态变量等). #include <iostream.h> class Person { public: person() {cout<<"Construction of person."<<endl;} ~person() {cout<<"Destr

C++语言笔记系列之十——静态成员

1.静态成员 (1)由关键字static修饰 静态变量定义语句在编译阶段就执行,运行过程中不再执行. (2)分类:静态数据成员.静态成员函数. (3)静态成员时类的所有对象共享的成员,而不是某一个对象的成员. 2.静态成员的使用 (1)在定义说明前加上static关键字.例如: static int x: (2)静态数据成员必须进行初始化,并且初始化必须在类外完成. (3)静态数据成员的初始化 数据类型 类名::静态数据成员名 = 值://注意这里没有static出现 (4)绝对不能使用对象名来

C++语言笔记系列之十七——虚基类

1.虚基类 考虑这样一种情况:当某个类的部分或者全部直接基类是另一个共同基类派生而来,这些直接基类从上一级基类继承而来的成员就一定拥有相同的名称,这样就会产生二义性问题. 解决办法:当派生类和直接基类产生了二义性问题-->加类的作用域. 当派生类和间接基类产生了二义性问题-->虚基类. 2.虚基类的说明: class 派生类名:virtual 访问权限 基类名 {派生类定义}; 注意:在定义派生类时将需要继承的基类进行虚化声明,虚基类的说明在派生类的定义中完成. 作用:将基类说明为虚基类之后,

【C语言天天练(十九)】restrict关键词

引言:在内核的系统调用函数里,经常遇到函数的参数使用restrict限定词限定的情况,下面就对该关键词做个总结. 1.restrict关键词是C99特性才添加的,因此在编译使用含有该限定词的程序时,一定要在后边添加-std=c99的标志,使得gcc能够支持c99标准. 2.restrict既然是个限定词,那么它限定什么变量呢?它只能限定指针变量!经过它限定的数据对象,表明指针时访问该数据对象的唯一且初始的方式.注意:这里的唯一表明了,由它限定的指针所指向的数据块,只能由该指针访问,不能由除它之外

C++语言笔记系列之十三——派生类构造函数的调用

1.派生类构造函数的调用 (1)一个基类的所有数据成员均被派生类继承.创建一个派生类对象时,系统在为派生类对象分配单元时一定要为其基类数据成员分配子空间. (2)一个派生类对象在创建时不仅要调用派生类构造函数,而且要调用基类构造函数. 派生类中的数据成员在派生类中构造. 基类中的数据成员在基类中构造. 原因: A.构造函数不继承. B.派生类的构造函数必须通过调用基类的构造函数完成基类数据成员的初始化. C.若派生类中含有子对象,必须调用子对象的构造函数. 2.派生类的构造函数 派生类名(总参数