C++ 实用泛型编程之 虚拟函数(C++ virtual function)杂谈

一 C++虚拟函数(C++ virtual function)杂谈

我们在编程的时候,经常会遇到这样的情况,假设有两个对象,你要在函数中分别调用它们的OnDraw方法,我们以前的做法一般是这样的。

void f(int iType)

{

switch(iType)

{

case 1:

//CCircle OnDraw

break;

case 2:

//CRectangle OnDraw

break;

}

}

这种方法当然能解决我们的问题,但是如果有新的类型要增加,它就必须要往下加代码才行了,这样函数里的代码会越写越长。你可能会想我的类型不多,往下加也不会太长,但是这种想法是不可取的,因为实际工作当中,我们经常遇到的情况是,一个系统可能要维护好几年,甚至10几年都会有,所以不可预知的事情很多,做设计的时候不能有这种侥幸心里。C++中提供了虚函数,可以方便我们解决这个问题。

class CShape

{

public:

virtual void OnDraw(){}

};

class CCircle:public CShape

{

public:

void OnDraw()

{

cout<<"CCircle OnDraw"<<endl;

}

};

class CRectangle: public CShape

{

void OnDraw()

{

cout<<"CRectangle OnDraw"<<endl;

}

};

定义一个接口函数,把基类作为型参,对象传入后就可以调用到对应的函数了。

void SelfDraw(CShape *_shap)

{

_shap->OnDraw();

}

在调用的时候只需要写类似如下的代码。

CCircle c1;

CRectangle r1;

SelfDraw(&c1);

SelfDraw(&r1);

程序编译运行后的结果如下。

可能刚学c++不久的朋友不知道为什么可以这样使用,为什么基类可以正确的调用到子类的函数,那么让我们来看看秘密到底在哪里吧。

秘密就是__vfptr(virtual function pointer),__vfptr是一个指针数组指向虚函数,当CCircle对象传入基类指针后,虚函数指针会指向CCircle重载的OnDraw函数,所以我们就会看到SelfDraw中_shap->OnDraw()可以正确调用到它对应子类函数了。

时间: 2024-12-28 02:51:09

C++ 实用泛型编程之 虚拟函数(C++ virtual function)杂谈的相关文章

虚拟继承下 Virtual Function 的语意

考虑下面的 virtual base class 派生体系: class Point2d { public: Point2d(float = 0.0, float = 0.0); virtual ~Point2d(); virtual void Mumble(); virtual float Z(); //... protected: float _x, _y; }; class Point3d:public virtual Point2d { public: Point3d(float = 0

C++ 实用泛型编程之设计通用型程序(模板)杂谈

上一节中我们讲到用基类做参数,可以实现不用判断子类对象类型,就能调用到对应的函数. 如果我们要设计一个堆栈,不管传入的数据类型,例如整形或字符型,都可以正确的处理,我们要怎么做呢?当然传统的方法我们也可以实现,但是不太好做,比较麻烦.现在我们来介绍一下更通用的一个方法.C++ STL提供了容器(Container),现在我们来看下容器stack怎么实现的. template<typename T> class Stack { public: ~Stack(){} Stack(int _i):m

学习笔记之深入浅出MFC 第8章 C++重要性质----虚拟函数与多态(Polymorphism)

1.虚拟函数的由来 上面我们曾经提过一个例子: CShape shapes[5]; . . . //令5个shapes各为矩形.正方形.椭圆形.圆形.三角形 for ( int i = 0;  i<5;  i++) { shapes[i].display(); } 在上一节中我们说这种一般化的操作无法完成.你还记得为什么吗?是这样的,上面一节中讲到,由于每一个子类图形的绘制不同,所以display()各不相同,所以无法提升到基类中去.那么用基类定义的shapes[]数组,当然也就没有displa

MySQL 5.7 虚拟列 (virtual columns)

参考资料: Generated Columns in MySQL 5.7.5 MySQL 5.7新特性之Generated Column(函数索引) MySQL 5.7原生JSON格式支持 Generated Column 在MySQL 5.7中,支持两种Generated Column,即Virtual Generated Column和Stored Generated Column,前者只将Generated Column保存在数据字典中(表的元数据),并不会将这一列数据持久化到磁盘上:后者

ftp 实用户和虚拟用户共存设置

老习惯先吐槽,总共花费接近6个小时,遇到各种奇葩问题,决定把问题记录下来,作为知识储备~ 调整前背景: vsftp已有全部为实体用户,不同的用户对不同的目录有权限,但现在由于需求,后续接近上百的用户要使用不同账号,且不同账号对不同目录有不同权限,这种需求创建实体用户是不现实的,且以后做ftp迁移也极为不方便. 操作步骤: 1.修改配置文件 /etc/vsftpd/vsftpd.conf user_config_dir=/etc/vsftpd/userconfig (该配置已存在,用于控制用户的不

C++中的虚函数解析[The explanation for virtual function of CPlusPlus]

1.什么是虚函数?                                                                                                                                               答:在C++的类中,使用virtual修饰的函数. 例如: virtual void speak() const { std::cout << "Mammal speak!\n&quo

Oracle 11g新特性之--虚拟列(Virtual Column)

Oracle 11g新特性之--虚拟列(Virtual Column) Oracle 11G虚拟列Virtual Column介绍 Oracle 11G 在表中引入了虚拟列,虚拟列是一个表达式,在运行时计算,不存储在数据库中,不能更新虚拟列的值. 定义一个虚拟列的语法: column_name [datatype] [GENERATED ALWAYS] AS [expression] [VIRTUAL] 1.虚拟列可以用在select,update,delete语句的where条件中,但是不能用

C++虚拟函数

一 为了方便使用多态特性,常常需要在基类中定义虚拟函数. 在很多情况下,积累本身生成对象是不合理的.例如,动物作为一个基类可以派生出猫.狗.猴子.熊.牛等子类,但动物本身生成对象明显不合常理. 为了解决上述问题,引入了纯虚函数的概念,江汉数定义为纯虚函数,编译器要求在派生类中必须予以重载以实现多态性. 同时,含有纯虚函数的类为抽象类,他不能生成对象. 纯虚函数的定义格式: virtual 类型 函数名=0; 二 测试代码如下: 1 #include <iostream> 2 3 using n

纯虚拟函数的存在 &amp; 虚拟规格的存在, 及其中 const 的存在

考察以下代码: class AbstractBase { public: virtual IBase() = 0; virtual Interface() const = 0; virtual const char* Member() const {return _member;} protected: char *_member; } 这段代码有个问题, 虽说这个类是个抽象的, 但它仍然需要一个构造函数来初始化 _member. 可能有人觉得, 这个 AbstractBase 的设计者试图让每