虚函数的作用和意义,就不进行说明了,这里主要讨论下虚函数的用法。

1.典型的虚函数用法

可以看到,只有标识为virtual的函数才会产生多态的效果,而且是编译多态。它只能借助指针或者引用来达到多态的效果。

class A
{
public:
virtual void f(){cout<<"A::f()";}//虚函数
void g(){cout<<"A::g()";}//普通函数
}; class B :public A{
public:
virtual void f(){cout<<"B::f()";}
void g(){cout<<"B::g()";}
}; class C :public A{
public:
virtual void f(){cout<<"C::f()";}
void g(){cout<<"C::g()";}
}; int _tmain(int argc, _TCHAR* argv[])
{
A* pa=new B;//pa是指针喔
pa->f(); // 调用B::f()
pa->g(); // 调用A::g()
delete pa; pa=new C;
pa->f(); // 调用C::f()
pa->g(); // 调用A::g()
delete pa; pa=NULL;
return 0;
}

2.虚函数的默认继承

虚函数是默认继承virtual属性的,即使在子类中没有标识virtual。

class A
{
public:
virtual void f(){cout<<"A::f()";}
}; class B :public A{
public:
void f(){cout<<"B::f()";}//不加virtual了
}; class C :public B{
public:
void f(){cout<<"C::f()";}//也不加virtual了
}; int _tmain(int argc, _TCHAR* argv[])
{
A* pa=new B;
pa->f(); // 调用B:f()
delete pa; pa=new C;
pa->f(); // 调用C:f()
delete pa; pa=NULL;
return 0;
}

3.纯虚函数

纯虚函数和Java中的接口很像了,因为纯虚函数的存在导致了该类成了抽象类,它的主要作用就是规范接口,把实现留给子类。如果子类没有实现它的所有虚函数,那么该子类也是一个抽象类,通用不能进行实例化。

class A
{
public:
virtual void f()=0;//纯虚函数,导致该类为抽象类
}; class B :public A{
public:
virtual void f(){cout<<"B::f()";}
}; int _tmain(int argc, _TCHAR* argv[])
{
//A* pa=new A;//出错,不能实例化抽象类
A* pa=new B;
pa->f();//调用B::f()
delete pa; pa=NULL;
return 0;
}

4.虚函数的调用模型

子类调用父类函数只有虚函数才得以执行,普通函数只会调用父类函数,不过要注意以下的h()可不能是构造函数或者析构函数,不然多态就无法实现。

class A
{
private:
virtual void f(){cout<<"A::f()"<<endl;}
void g(){cout<<"A::g()"<<endl;}
public:
void h(){f();g();}
}; class B :public A{
private:
virtual void f(){cout<<"B::f()"<<endl;}
void g(){cout<<"B::g()"<<endl;}
}; int _tmain(int argc, _TCHAR* argv[])
{
B b;
b.h();//调用父类的h(),分别再调用f()和g()。f()为虚函数调用子类B::f(),g()为普通函数调用父类A::g()。 return 0;
}

5.虚析构函数

虚构函数可以是虚函数,甚至是纯虚函数。如果它作为一个基类,那析构函数必须是虚函数。

而构造函数不能是虚函数。

class A
{
public:
A(){p_a=new char[1];cout<<"new 1"<<endl;}
virtual ~A(){delete[] p_a;cout<<"delete 1"<<endl;}//正常
//~A(){delete[] p_a;cout<<"delete 1"<<endl;}//异常,内存泄漏,~B()并没有被执行到
private:
char* p_a;
}; class B :public A{
public:
B(){p_b=new char[2];cout<<"new 2"<<endl;}
~B(){delete[] p_b;cout<<"delete 2"<<endl;}//能不能正确执行~B()成了关键
private:
char* p_b;
}; int _tmain(int argc, _TCHAR* argv[])
{
A* pa=new B;
delete pa; return 0;
}

【C++基础之十一】虚函数的用法的更多相关文章

  1. C++基础(纯虚函数与抽象类)

    C++基础之纯虚函数与抽象类 引言 纯虚函数在C++编程中的地位很重要,其关联到了设计模式中"接口"的概念. 语法 纯虚函数的语法: 1.  将成员函数声明为virtual 2.  ...

  2. c++复习基础要点02 虚函数与模板 与static inline是否共存

    1.      虚函数能否定义为模板函数 当一个类有虚函数时,它一定有一个虚表,用来纪录每个虚函数的实际地址.这也就是说这个虚表的大小是在编译期就确定了的.有多少个虚函数,虚表就纪录几个.       ...

  3. C#基础(七)虚函数

    若一个实例方法声明前带有virtual关键字,那么这个方法就是虚方法.虚方法与非虚方法的最大不同是,虚方法的实现可以由派生类所取代,这种取代是通过方法的重写实现的(以后再讲)虚方法的特点:虚方法前不允 ...

  4. 【C++基础】 多态 虚函数

    多态:同样的消息被不同类型的对象接收时导致不同的行为.这里“消息”是对类的成员函数的调用,“行为”调用了不同的函数. 分类:①重载多态 ②包含多态……等 实现:编译时的多态  运行时的多态(动态绑定) ...

  5. C++纯虚函数

    本文较为深入的分析了C++中虚函数与纯虚函数的用法,对于学习和掌握面向对象程序设计来说是至关重要的.具体内容如下: 首先,面向对象程序设计(object-oriented programming)的核 ...

  6. C++ 虚函数 、纯虚函数、接口的实用方法和意义

    也许之前我很少写代码,更很少写面向对象的代码,即使有写多半也很容易写回到面向过程的老路上去.在写面向过程的代码的时候,根本不管什么函数重载和覆盖,想到要什么功能就变得法子的换个函数名字,心里想想:反正 ...

  7. C++虚函数的新用法

    1.今天在segmentfault上看到了一个C++虚函数的新用法,先上代码 #include <iostream> using namespace std; class B { publ ...

  8. C++学习7-面向对象编程基础(多态性与虚函数、 IO文件流操作)

    多态 多态性是指对不同类的对象发出相同的消息将返回不同的行为,消息主要是指类的成员函数的调用,不同的行为是指不同的实现: 函数重载 函数重载是多态性的一种简单形式,它是指允许在相同的作用域内,相同的函 ...

  9. C++语言基础(12)-虚函数

    一.虚函数使用的注意事项 1.只需要在虚函数的声明处加上 virtual 关键字,函数定义处可以加也可以不加. 2.为了方便,你可以只将基类中的函数声明为虚函数,这样所有子类中具有遮蔽(覆盖)关系的同 ...

随机推荐

  1. floor() 和 ceil()函数

    在C语言的库函数中,floor函数的语法例如以下: #include <math.h> double floor( double arg ); 功能: 函数返回參数不大于arg的最大整数. ...

  2. Cocos2dx 多线程

    多-threaded负荷plist特征.获取知识的必要性: 1.多线程开启:pthread 2.怎样在线程中载入plist 一.多线程开启 当我们想在程序中开多线程中.第一想到的是cocos2d-x有 ...

  3. Task的运行过程分析

    Task的运行过程分析 Task的运行通过Worker启动时生成的Executor实例进行, caseRegisteredExecutor(sparkProperties)=> logInfo( ...

  4. VB.NET 数组的定义 动态使用 多维数组

    我们都知道在全部程序设计语言中数组都是一个非常重要的概念,数组的作用是同意程序猿用同一个名称来引用多个变量,因此採用数组索引来区分这些变量.非常多情况下利用数组索引来设置一个循环,这样就能够高效地处理 ...

  5. ORACLE函数之单行数字函数

     1.           ABS(X) 返回X的绝对值 SQL>SELECT ABS(-1) A,ABS(1) B,ABS(0) C FROM DUAL; A          B     ...

  6. CSS和CSS3中的伪元素和伪类(总结)

    好多人伪类和伪元素分清楚,其实就是一句话,“伪类的效果可以通过添加一个实际的类来达到,而伪元素的效果则需要通过添加一个实际的元素才能达到”. CSS中伪类包括: :first-child :lang ...

  7. 单篇文章JS模拟分页

    废话部分 前两天做了一个前台分页插件,支持ajax读取数据绑定前台 和 url带页码参数跳转两种方式.于是稍加改动,做了一个单篇文章js模拟分页的代码,为什么说是模拟分页呢?因为在服务器响应HTML请 ...

  8. C#线程 访问资源同步简介

    在多线程应用(一个或多个处理器)的计算中会使用到同步这个词.实际上,这些应用程序的特点就是它们拥有多个执行单元,而这些单元在访问资源的时候可能会发生冲突.线程间会共享同步对象,而同步对象的目的在于能够 ...

  9. (转)TortoiseSVN使用简介

    TortoiseSVN使用简介 TortoiseSVN使用简介 2009-04-24 来源:dev.idv.tw 1 安装及下载client 端 2 什么是SVN(Subversion)? 3 为甚么 ...

  10. java.lang.NumberFormatException: empty String 错误

    原因:前台获取的字符串,后台类型转换,与之对应的实体类中却是Integer类型,所以会报错. 排错情况:1.先检查数据库与实体类中的类型是否一致 2.检查类型转换代码,如果需要加入异常处理