通过基类指针只能访问派生类的成员变量,但是不能访问派生类的成员函数。

为了消除这种情况,让基类指针能够访问派生类的成员函数,C++ 增加了虚函数(Virtual Function)。使用虚函数,需要在函数声明前面增加 virtual 关键字。

#include <windows.h>
#include "resource.h"
#include <string>using namespace std;char szBuffer[100];  //基类People
class People{
public:People(char *name, int age);virtual void display(HDC hdc);  //声明为虚函数
protected:char *m_name;int m_age;
};
People::People(char *name, int age): m_name(name), m_age(age){}
void People::display(HDC hdc){wsprintf(szBuffer, "%s今年%d岁了,是个无业游民。",m_name,m_age);TextOut(hdc,10,30,szBuffer,lstrlen(szBuffer));}
//派生类Teacher
class Teacher: public People{
public:Teacher(char *name, int age, int salary);virtual void display(HDC hdc);  //声明为虚函数
private:int m_salary;
};
Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}
void Teacher::display(HDC hdc){wsprintf(szBuffer, "%s今年%d岁了,是一名教师,每月有%d元的收入",m_name,m_age,m_salary);TextOut(hdc,10,80,szBuffer,lstrlen(szBuffer));
}LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);HINSTANCE hInst;
TCHAR szClassName[] = TEXT("virtfDemo");int WINAPI
WinMain (HINSTANCE hThisInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nFunsterStil)
{HWND hwnd;MSG messages;WNDCLASSEX wincl;hInst = hThisInstance;wincl.hInstance = hThisInstance;wincl.lpszClassName = szClassName;wincl.lpfnWndProc = WindowProcedure;wincl.style = CS_DBLCLKS;wincl.cbSize = sizeof (WNDCLASSEX);wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);wincl.hCursor = LoadCursor (NULL, IDC_ARROW);wincl.lpszMenuName = MAKEINTRESOURCE (IDC_VIRTFDEMO);wincl.cbClsExtra = 0;wincl.cbWndExtra = 0;wincl.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);if (!RegisterClassEx (&wincl))return 0;hwnd = CreateWindowEx (0,szClassName,TEXT("C++虚函数Demo"),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,400,200,HWND_DESKTOP,NULL,hThisInstance,NULL);ShowWindow (hwnd, nFunsterStil);while (GetMessage (&messages, NULL, 0, 0)){TranslateMessage(&messages);DispatchMessage(&messages);}return messages.wParam;
}LRESULT CALLBACK
WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{PAINTSTRUCT ps;HDC hdc;RECT rt;    char szBuffer[100]; People *p = new People("王不二", 23);switch (message){case WM_COMMAND:switch (LOWORD(wParam)){case IDM_virtf:hdc=GetDC(hwnd);p -> display(hdc);p = new Teacher("赵杰杰", 45, 9000);p -> display(hdc);break;case IDM_ABOUT:MessageBox (hwnd, TEXT ("virtfDemo v1.0\nCopyright (C) 2020\n by bo"),TEXT ("virtfDemo"), MB_OK | MB_ICONINFORMATION);break;case IDM_EXIT:DestroyWindow(hwnd);break;default:return DefWindowProc(hwnd, message, wParam, lParam);               }break;case WM_CREATE:break;case WM_PAINT:hdc = BeginPaint(hwnd, &ps);                 GetClientRect(hwnd, &rt);               EndPaint(hwnd, &ps);break;case WM_DESTROY:PostQuitMessage (0);break;default:return DefWindowProc (hwnd, message, wParam, lParam);}return 0;
}

例子中,可以通过 p 指针调用 Teacher 类的成员函数,运行结果也证明了这一点(赵杰杰已经是一名老师了,不再是无业游民)。

有了虚函数,基类指针指向基类对象时就使用基类的成员(包括成员函数和成员变量),指向派生类对象时就使用派生类的成员。换句话说,基类指针可以按照基类的方式来做事,也可以按照派生类的方式来做事,它有多种形态,或者说有多种表现方式,这就是 多态(Polymorphism)

同样是p->display();这条语句,当 p 指向不同的对象时,它执行的操作是不一样的。同一条语句可以执行不同的操作,看起来有不同表现方式,这就是多态。

多态是面向对象编程的主要特征之一,C++中虚函数的唯一用处就是构成多态。

工程;

资源和头文件;

#include "resource.h"
#include <windows.h>/
//
// Menu
//IDC_VIRTFDEMO MENU
BEGINPOPUP "&File"BEGINMENUITEM "C++虚函数",                 IDM_virtfMENUITEM "E&xit",                    IDM_EXITENDPOPUP "&Help"BEGINMENUITEM "&About ...",             IDM_ABOUTEND
END
#define  IDM_EXIT        10001
#define     IDM_ABOUT       10002#define    IDC_VIRTFDEMO       10101
#define     IDD_ABOUTBOX    10102
#define     IDM_virtf        40001

C++虚函数Demo - Win32 版本相关推荐

  1. C语言回调函数Demo - Win32版

    回调函数:通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定的事件 ...

  2. C++多态虚函数/纯虚函数demo

    #include <iostream> using namespace std;class A //A是一个抽象类,不能new A直接实例化. { public:virtual void ...

  3. C++多态虚函数demo

    #include<iostream> #include<algorithm> using namespace std;class Base{ public:void Fun(i ...

  4. C++ const成员Demo - Win32 版本

    在类中,如果不希望某些数据被修改,可以使用const关键字加以限定.const 可以用来修饰成员变量和成员函数. const成员变量 const 成员变量的用法和普通 const 变量的用法相似,只需 ...

  5. C语言二级指针Demo - Win32 版本

    指针可以指向一份普通类型的数据,也可以指向一份指针类型的数据. 一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针. 假设有一个 int 类型的变量 a,p1是指向 a 的指针变量 ...

  6. 一口气搞懂《虚函数和纯虚函数》

    学习C++的多态性,你必然听过虚函数的概念,你必然知道有关她的种种语法,但你未必了解她为什么要那样做,未必了解她种种行为背后的所思所想.深知你不想在流于表面语法上的蜻蜓点水似是而非,今天我们就一起来揭 ...

  7. c++ 虚函数,纯虚函数的本质区别

    转载博客:https://mp.weixin.qq.com/s?__biz=MzAxNzYzMTU0Ng==&mid=2651289202&idx=1&sn=431ffd1fa ...

  8. 虚函数和纯虚函数详解

    https://mp.weixin.qq.com/s?__biz=MzAxNzYzMTU0Ng==&mid=2651289202&idx=1&sn=431ffd1fae4823 ...

  9. 一个例子彻底搞懂C++的虚函数和纯虚函数

    学习C++的多态性,你必然听过虚函数的概念,你必然知道有关她的种种语法,但你未必了解她为什么要那样做,未必了解她种种行为背后的所思所想.深知你不想在流于表面语法上的蜻蜓点水似是而非,今天我们就一起来揭 ...

最新文章

  1. Tomcat的安装和环境变量配置
  2. Java高并发编程(七):读写锁、LockSupport、Condition
  3. 【面试必备】Swiftamp;nbsp;面试题及其答案
  4. 剑指offer之46-50题解
  5. linux cmake装在自己目录下,如何在Linux下安装cmake
  6. Seeing this, many people find it incredible
  7. hibernate第一天
  8. Java 设计模式 之 适配器模式(Adapter)
  9. iOS开发:2分钟快速集成支付宝快捷支付
  10. 【华为二面】2020/3/25_华为第二次技术面试_45分钟
  11. Numpy的各种下标操作
  12. 20172303 2017-2018-2 《程序设计与数据结构》第10周学习总结
  13. elasticsearch中基于slop参数实现近似匹配
  14. 写公众号一个月关注量破900,聊聊我的感受
  15. 论文降重的方法是什么?
  16. 网上流传的《名侦探柯南》大结局十二种!
  17. 【Crypto】BUGKU-抄错的字符
  18. 2020年度总结——魔幻的一年,魔幻的我
  19. NOJ-1149-旅游预算
  20. 本科生如何进行文献阅读和文献整理?

热门文章

  1. 通话录音_谁说苹果手机不能通话录音?四种方法教给你!别再说你不知道了
  2. python类成员_Python的类成员和对象成员
  3. java的知识点13——多态、对象的转型(casting)、final关键字、抽象方法和抽象类、接口的作用、如何定义和使用接口?、接口的多继承、面向接口编程
  4. 使用axios上传文件+参数
  5. DIV CSS left right top bottom定位
  6. Python 调用有道翻译api接口翻译外文网站的整篇西班牙文实战演示
  7. C++ leetcode 7. 整数反转 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
  8. 微信小程序中base64格式的小程序码通过canvas画出来无效
  9. CTFshow php特性 web149
  10. 第四周实践项目7 多项式求和