当前位置:  编程技术>c/c++/嵌入式

c++ 虚函数与纯虚函数的区别(深入分析)

    来源: 互联网  发布时间:2014-10-16

    本文导语:  在面向对象的C++语言中,虚函数(virtual function)是一个非常重要的概念。因为它充分体现 了面向对象思想中的继承和多态性这两大特性,在C++语言里应用极广。比如在微软的MFC类库中,你会发现很多函数都有virtual关键字,也...

在面向对象的C++语言中,虚函数(virtual function)是一个非常重要的概念。因为它充分体现 了面向对象思想中的继承和多态性这两大特性,在C++语言里应用极广。比如在微软的MFC类库中,你会发现很多函数都有virtual关键字,也就是说, 它们都是虚函数。难怪有人甚至称虚函数是C++语言的精髓。
那么,什么是虚函数呢,我们先来看看微软的解释:
虚函数是指一个类中你希望重载的成员函数,当你用一个基类指针或引用指向一个继承类对象的时候,你调用一个虚函数,实际调用的是继承类的版本。                                                          这个定义说得不是很明白。MSDN中还给出了一个例子,但是它的例子也并不能很好的说明问题。我们自己编写这样一个例子:
代码如下:

#include "stdio.h"
#include "conio.h"
class Parent
{    
public:
    char data[20];    
    void Function1();
    virtual void Function2(); // 这里声明Function2是虚函数    
}parent;
void Parent::Function1()
{
    printf("This is parent,function1n");
}
void Parent::Function2()
{
    printf("This is parent,function2n");
}
class Child: public Parent
{
    void Function1();
    void Function2();

} child;
void Child::Function1()
{
    printf("This is child,function1n");
}
void Child::Function2()
{
    printf("This is child,function2n");
}
int main(int argc, char* argv[])
{    
    Parent *p; // 定义一个基类指针    

    if ( _getch()=='c' ) // 如果输入一个小写字母c
        p=&child; // 指向继承类对象
    else
        p=&parent; // 否则指向基类对象

    p->Function1(); // 这里在编译时会直接给出Parent::Function1()的 入口地址。   
    p->Function2(); // 注意这里,执行的是哪一个Function2?

    return 0;
}

用任意版本的Visual C++或Borland C++编译并运行,输入一个小写字母c,得到下面的结果:
This is parent,function1
This is child,function2
为什么会有第一行的结果呢?因为我们是用一个Parent类的指针调用函数Fuction1(),虽然实际上这个指针指向的是Child类的对象,但编译器 无法知道这一事实(直到运行的时候,程序才可以根据用户的输入判断出指针指向的对象),它只能按照调用Parent类的函数来理解并编译,所以我们看到了 第一行的结果。
  
那么第二行的结果又是怎么回事呢?我们注意到,Function2()函数在基类中被virtual关键字修饰,也就是 说,它是一个虚函数。虚函数最关键的特点是“动态联编”,它可以在运行时判断指针指向的对象,并自动调用相应的函数。如果我们在运行上面的程序时任意输入 一个非c的字符,结果如下:
This is parent,function1
This is parent,function2
  
请注意看第二行,它的结果出现了变化。程序中仅仅调用了一个Function2()函数,却可以根据用户的输入自动决定到底调用基类中的Function2 还是继承类中的Function2,这就是虚函数的作用。我们知道,在MFC中,很多类都是需要你继承的,它们的成员函数很多都要重载,比如编写MFC应 用程序最常用的CView::OnDraw(CDC*)函数,就必须重载使用。把它定义为虚函数(实际上,在MFC中OnDraw不仅是虚函数,还是纯虚 函数),可以保证时刻调用的是用户自己编写的OnDraw。虚函数的重要用途在这里可见一斑。
-----------------------------------------------------------
再看下面的
派生类的大小问题C++中虚函数和纯虚函数的概念,差别和分别存在的原因
首先:强调一个概念
定义一个函数为虚函数,不代表函数为不被实现的函数,定义它为虚函数是为了允许用基类的指针来调用子类的这个函数
定义一个函数为纯虚函数,才代表函数没有被实现,定义他是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
对继承的影响:
普通的类(没有虚函数,纯虚函数)就可以被继承,而且工作的相当好
关于这个问题有以下疑问:
纯虚函数难道就是为了实现接口?接口存在的意义?
我实在弄不懂,我干嘛要预先定义好?未来的事情本难料,就等有一天我的类中需要使用某个函数,在添加一个函数不就可以?
关于实例化一个类:
有纯虚函数的类是不可能生成类对象的,如果没有纯虚函数则可以。比如:
代码如下:

class CA
{
public:
    virtual void fun() = 0; // 说明fun函数为纯虚函数
    virtual void fun1();
};
class CB
{
public:
    virtual void fun();
    virtual void fun1();
};
// CA,CB类的实现
...
void main()
{
    CA a; // 不允许,因为类CA中有纯虚函数
    CB b; // 可以,因为类CB中没有纯虚函数

    ...
}

---------------------------------------------------------------
虚函数在多态中间的使用:
多态一般就是通过指向基类的指针来实现的。
dog mydogwangwang;
mydogwangwang.born();
一定是返回“dog”
那么
horse myhorsepipi;
myhorsepipi.born();
一定是返回“horse”
也是多态呀?
/////////////////////////////////////////////////
有一点你必须明白,就是用父类的指针在运行时刻来调用子类:
例如,有个函数是这样的:
代码如下:

void animal::fun1(animal *maybedog_maybehorse)
{
     maybedog_maybehorse->born();
}

参数maybedog_maybehorse在编译时刻并不知道传进来的是dog类还是horse类,所以就把它设定为animal类,具体到运行时决定了才决定用那个函数。
也就是说用父类指针通过虚函数来决定运行时刻到底是谁而指向谁的函数。
代码如下:

//用虚函数
#include
class animal
{
public:
    animal();
    ~animal();
    void fun1(animal *maybedog_maybehorse);
    virtual void born();
};
void animal::fun1(animal *maybedog_maybehorse)
{
    maybedog_maybehorse->born();
}
animal::animal()
{
}
animal::~animal()
{
}
void animal::born()
{
    cout

    
 
 

您可能感兴趣的文章:

  • C++ Maps 成员 key_comp():返回比较元素key的函数
  • 怎么样在C++里调用Fortran函数??????
  • C++ Maps 成员 value_comp():返回比较元素value的函数
  • SOS ,在UNIX下编译C++程序时出现链接错误:未下义的符号,但函数库里有这些函数,不知道为什么?
  • C++ MultiMaps 成员 key_comp():返回比较key的函数
  • 求linux C++的时间相关函数及用法,急用,谢谢
  • C++ MultiMaps 成员 value_comp():返回比较元素value的函数
  • C++ 函数编程库 FC++
  • C++ Strings(字符串) 成员 Constructors:构造函数,用于字符串初始化
  • C++ 程序中,如何增加c函数?
  • Linux c++虚函数(virtual function)简单用法示例代码
  • C++中虚拟函数表的问题
  • C++ STL Bitsets构造函数及成员函数解释及代码示例
  • linux下编译c++程序,系统头文件中包含的函数的定义源代码可以查看吗?
  • c++ stl容器set成员函数介绍及set集合插入,遍历等用法举例
  • Linux中的共享库难道只能导出函数,而不能导出C++类吗?
  • c++断言assert()函数的头文件及其用法详解
  • 常用C++函数库 Libretta
  • Windows和Linux下C++类成员方法作为线程函数方法介绍
  • C++空类默认函数详细解析
  • IT科技资讯 iis7站长之家
  • 如何在C程序中调用C++中的函数
  • 深入mysql YEAR() MONTH() DAYOFMONTH()日期函数的详解
  • 内联函数inline与宏定义深入解析
  • 虚函数与纯虚函数(C++与Java虚函数的区别)的深入分析
  • SQL SERVER函数之深入表值函数的处理分析
  • 深入探讨:main函数执行完毕后,是否可能会再执行一段代码?
  • 深入解析函数指针与返回函数的指针
  • 基于memset()函数的深入理解
  • C语言typedef与复杂函数声明问题的深入解析
  • 深入VC回调函数的使用详解
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • linux c 生成随机数srand函数和rand函数介绍及代码示例
  • 请问:定义了2个函数,其中第一个函数要访问另外一个函数的变量,怎么处理阿?谢谢
  • Linux下gettimeofday()函数和clock()函数:精确到毫秒级的时间
  • 如果知道一个函数的地址或函数名,如何得到函数所在的文件名?
  • sharepoint 2010 使用STSNavigate函数实现文件下载举例
  • java的数学函数在那个类中,如幂函数、指数、对数、双曲线函数等?
  • cityhash 32位,64位和128位介绍及函数列表
  • 一个父类的构造函数的参数是(Applet applet),请问它的子类构造函数当中应怎样调用父类构造函数?
  • PHP的substr() 函数用法
  • 虚函数被类的构造析构函数和成员函数调用虚函数的执行过程
  • linux c下利用srand和rand函数生成随机字符串
  • 在内核的某个函数中,如何能知道是哪个用户空间的函数调用了它,以及这个用户空间函数所在的文件?
  • Python类的构造函数,析构函数以及垃圾回收机制详细介绍及代码举例
  • 在dos下访问内存的MK_FP函数在linux下对应什么函数?int86()函数呢?
  • Linux下c基于openssl生成MD5的函数
  • 一个静态库包含多个函数,应用程序连接了库中的某个函数,应用程序目标代码中是否还包含了该静态库中的其他函数代码?
  • Linux下c函数dlopen实现加载动态库so文件代码举例
  • Oracle 函数大全[字符串函数,数学函数,日期函数]第1/4页
  • Linux Kernel 'sctp_v6_xmit()'函数信息泄露漏洞
  • js的众多函数令小弟实在搞不清楚!哪有函数速查手册之类的软件或者书籍!谢了!比如,setInterval、clearInterval这两个函数是干什么的?
  • 哈希函数的构造方法及举例
  • 谁能告诉我,在JAVA中,哪个函数和ASP中的Int()函数等同,也就是取整函数




  • 特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3