C++之普通成员函数、虚函数以及纯虚函数的区别与用法要点

C++虚函数纯虚函数、抽象函数、接口类、抽象类的区别联系 虚函数纯虚函数、抽象函数、接口类、抽象类是C++中实现多态面向对象设计的重要概念。:接口类是一种特殊的抽象类,只包含纯虚函数(没有实现)静态成员变量,不能包含普通成员函数数据成员。:抽象类用于定义一个通用的框架或接口,强制派生类实现特定的功能。抽象类的目的是定义一个通用的框架,而不是提供完整的实现。:定义通用框架,提供部分实现,强制派生类实现特定功能。:没有默认实现(但可以有默认实现),派生类必须实现。:定义一组功能规范,强制派生类实现,实现松耦合。:纯虚函数用于定义接口,强制派生类实现该函数。 阅读详情

普通成员函数是静态编译的,没有运行时多态,只会根据指针或引用的“字面值”类对象,调用自己的普通函数;虚函数为了重载和多态的需要,在基类中定义的,即便定义为空;纯虚函数是在基类中声明的虚函数,它可以再基类中有定义,且派生类必须定义自己的实现方法。

假设我们有三个类Person、Teacher、Student它们之间的关系如下:


这里写图片描述
类的关系图

普通成员函数

【Demo1】

根据这个类图,我们有下面的代码实现

#ifndef __OBJEDT_H__
#define __OBJEDT_H__
 
#include <string>
#include <iostream>
 
class Person
{
public:
 Person(const string& name, int age) : m_name(name), m_age(age)
 {
 }
 
 void ShowInfo()
 {
 cout << "姓名:" << m_name << endl;
 cout << "年龄:" << m_age << endl;
 }
 
protected:
 string m_name; //姓名
 int m_age; //年龄
};
 
 
class Teacher : public Person
{
public:
 Teacher(const string& name, int age, const string& title)
 : Person(name, age), m_title(title)
 {
 }
 
 void ShowInfo()
 {
 cout << "姓名:" << m_name << endl;
 cout << "年龄:" << m_age << endl;
 cout << "职称:" << m_title << endl;
 }
 
private:
 string m_title; //职称
};
 
class Student : public Person
{
public:
 Student(const string& name, int age, int studyId)
 : Person(name, age), m_studyId(studyId)
 {
 }
 
 void ShowInfo()
 {
 cout << "姓名:" << m_name << endl;
 cout << "年龄:" << m_age << endl;
 cout << "学号:" << m_studyId << endl;
 }
 
private:
 int m_studyId;  //学号
};
 
#endif //__OBJEDT_H__

测试代码:

void test()
{
 Person* pPerson = new Person("张三", 22);
 Teacher* pTeacher = new Teacher("李四", 35, "副教授");
 Student* pStudent = new Student("王五", 18, 20151653);
 pPerson->ShowInfo();
 cout << endl;
 pTeacher->ShowInfo();
 cout << endl;
 pStudent->ShowInfo();
 cout << endl;
 delete pPerson;
 delete pTeacher;
 delete pStudent;
}

结果:

姓名:张三
年龄:22

姓名:李四
年龄:35
职称:副教授

姓名:王五
年龄:18
学号:20151653
说明:
这里的ShowInfo就是一个普通的函数。pPerson、pTeacher和pStudent三个对象调用ShowInfo分别展示自己的信息。
我们知道:父类的指针是可以指向子类的对象的。我们把上面的测试代码稍微改一下:
【Demo2】

void test()
{
 Person* pPerson = new Person("张三", 22);
 Person* pTeacher = new Teacher("李四", 35, "副教授");
 Person* pStudent = new Student("王五", 18, 20151653);
 pPerson->ShowInfo();
 cout << endl;
 pTeacher->ShowInfo();
 cout << endl;
 pStudent->ShowInfo();
 cout << endl;
 delete pPerson;
 delete pTeacher;
 delete pStudent;
}

结果:

姓名:张三
年龄:22

姓名:李四
年龄:35

姓名:王五
年龄:18
这时,pTeacher和pStudent只输出了姓名和年龄,并没有输出子类所具有的特性(职称和学号)。这应该不是你期望的结果,你可能期望pTeacher和pStudent输出老师和学生的完整信息,这时就需要用虚函数。

虚函数

我们把Person中的ShowInfo成员改成虚函数(在前面加上virtual),代码如下:
【Demo3】

class Person
{
public:
 Person(const string& name, int age) : m_name(name), m_age(age)
 {
 }
 
 virtual void ShowInfo()
 {
 cout << "姓名:" << m_name << endl;
 cout << "年龄:" << m_age << endl;
 }
 
protected:
 string m_name; //姓名
 int m_age; //年龄
};

在执行上面【Demo2】中的测试代码,得到我们想到的结果:

姓名:张三
年龄:22

姓名:李四
年龄:35
职称:副教授

姓名:王五
年龄:18
学号:20151653
虚函数用法要点:

  1. 虚函数的声明方式:virtual RETURN_TYPE functionName(ARGS 参数列表);
  2. 虚函数作用:现实C++中的多态,进行动态绑定(父类指针可指向子类的对象),直到运行时才知道要调用哪个版本(哪个类定义)的函数;
  3. 我们必要对虚函数进行定义;
  4. 一旦父类的成员函数声明virtual,其子类的函数不管有没有声明为virtual,都是虚函数;
  5. 如果虚函数使用默认实参,父类和子类定义的默认实参最好一致。

【Demo4】:针对第4点说明:

class Person
{
public:
 Person(const string& name, int age) : m_name(name), m_age(age)
 {
 }
 
 virtual void ShowInfo()
 {
 cout << "姓名:" << m_name << endl;
 cout << "年龄:" << m_age << endl;
 }
 
 string GetName(); //正确,普通函数如果不被使用,可以只有声明没有定义
 virtual int GetAge(); //错误,虚函数必须要有定义,即使是一个空实现,因为编译器无法确定会使用哪个函数
 
 
protected:
 string m_name; //姓名
 int m_age; //年龄
};

【Demo5】:针对第5点进行说明:
设计我们的类如下定义。


class Person
{
public:
 virtual void SetAge(int age = 0)
 {
 m_age = age;
 }
 //... 省略
};
 
 
class Teacher : public Person
{
public:
 virtual void SetAge(int age = 1)
 {
 m_age = age;
 }
 
 //... 省略
};
 
class Student : public Person
{
public:
 virtual void SetAge(int age = 2)
 {
 m_age = age;
 }
 
 //... 省略
};
 

测试1:

void test()
{
 Person* pPerson = new Person("张三", 22);
 Teacher* pTeacher = new Teacher("李四", 35, "副教授");
 Student* pStudent = new Student("王五", 18, 20151653);
 pPerson->SetAge();
 pTeacher->SetAge();
 pStudent->SetAge();
 
 pPerson->ShowInfo();
 cout << endl;
 pTeacher->ShowInfo();
 cout << endl;
 pStudent->ShowInfo();
 cout << endl;
 delete pPerson;
 delete pTeacher;
 delete pStudent;
}

结果:

姓名:张三
年龄:0

姓名:李四
年龄:1
职称:副教授

姓名:王五
年龄:2
学号:20151653
测试2:

void test()
{
 Person* pPerson = new Person("张三", 22);
 Person* pTeacher = new Teacher("李四", 35, "副教授");
 Person* pStudent = new Student("王五", 18, 20151653);
 pPerson->SetAge();
 pTeacher->SetAge();
 pStudent->SetAge();
 
 pPerson->ShowInfo();
 cout << endl;
 pTeacher->ShowInfo();
 cout << endl;
 pStudent->ShowInfo();
 cout << endl;
 delete pPerson;
 delete pTeacher;
 delete pStudent;
}

结果:

姓名:张三
年龄:0

姓名:李四
年龄:0
职称:副教授

姓名:王五
年龄:0
学号:20151653
纯虚函数

在上面的例子中,我们假设所有的人都要工作,但不同的人工作的方式不同。于是我们就要强制要求继承自Person的子类都要有工作的方法,这就需要纯虚函数。定义如下:
【Demo6】

class Person
{
public:
 //... 省略
 virtual void DoWork() = 0;
 //... 省略
};

但此时我们编译

Person* pPerson = new Person("张三", 22);

这句话时会报错:error C2259: ‘Person' : cannot instantiate abstract class
这是因为我们并没有为Person实现DoWork方法,而包含纯虚函数的类是一个抽象的类,抽象类不能被实例化。

于是我们在子类中对它实现如下:
【Demo7】

class Teacher : public Person
{
public:
 //... 省略
 virtual void DoWork()
 {
 cout << "教书..." << endl;
 }
 //... 省略
};
 
class Student : public Person
{
public:
 //... 省略
 virtual void DoWork()
 {
 cout << "学习..." << endl;
 }
 //... 省略
};

没用DoWork方法:

void test()
{
 Person* pTeacher = new Teacher("李四", 35, "副教授");
 Person* pStudent = new Student("王五", 18, 20151653);
 
 pTeacher->DoWork();
 cout << endl;
 pStudent->DoWork();
 cout << endl;
 
 delete pTeacher;
 delete pStudent;
}

 结果:

    教书…

    学习…
纯虚函数用法要点:

  1. 纯虚函数的声明方式:virtual RETURN_TYPE functionName(ARGS 参数列表) = 0;
  2. 含有纯虚函数的类是一个抽象的类,抽象类不能被实例化。
  3. 包含纯虚函数的抽象类常用来当作对外的接口,说明这个类有什么功能,而没有具体的实现,基体的实现交由子类完成。






C++继承中的普通函数,纯虚函数虚函数 C++ 在继承中虚函数纯虚函数普通函数,三者的区别 1.普通函数(no-virtual) 普通函数是静态编译的,没有运行时多态,只会根据指针或引用的“字面值”类对象,调用自己的普通函数。 普通函数是父类为子类提供的“强制实现”。 因此,在继承关系中,子类不应该重写父类的普通函数,因为函数的调用至于类对象的字面值有关。 2.纯虚函数(pure virtual) C++中包含纯虚函数的类,被称为是... 阅读详情

相关推荐

虚函数 纯虚函数 普通函数的区别

1.虚函数(impure virtual)   C++虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现。   子类可以重写父类的虚函数实现子类的特殊化。   如下就是一个父类中的虚函数: class A { public: virtual void out2(string s) { cout<<"A(out2):"<<s<<endl; } }; 2.纯虚函数(pure virtu

王者生辉的博客 4044

九、虚函数普通函数区别

虚函数 主要是为了多态。正常情况下,父类无法调用子类的成员函数,但是一旦子类的函数是虚函数,那么父类就可以调用该函数。案例如下: Parent *p = new Children(); //调用 Parent 类中的 method() 方法 p->method(); //调用 Children 类中的 virtualMethod() 方法 p...

panchang199266的博客 1684

c++基础】虚函数的使用以及成员函数区别

前言一直以来都知道虚函数的经典用法,但是除了本科时刚学c++的时候了解过,后来因为做不同的项目在不同的语言之间跳转(自觉都是浅尝辄止),这些基本的东西都忘记了,现在重拾并记录,权当巩固基础了。经典用法#include<iostream> using namespace std;//几何体类 class Geometry{ public: virtual void draw(){

XiaoHeiBlack的专栏 3151

虚函数普通成员函数区别

原文转载地址: https://blog.csdn.net/zxc024000/article/details/78784297

chengchaonan的博客 1750

C++ 虚函数纯虚函数:多态的核心实现基石

本文深入探讨了C++虚函数纯虚函数的核心概念及其在多态实现中的关键作用。主要内容包括: 虚函数:通过virtual关键字声明,实现运行时动态绑定,允许派生类重写基类函数。必须保持函数签名一致,建议使用override关键字显式声明。 纯虚函数:以"=0"结尾的无实现虚函数,使类成为抽象类,强制派生类实现所有纯虚函数。抽象类不能实例化,仅定义接口规范。 底层机制:详细解析了虚函数表(vtable)虚函数指针(vptr)的工作原理,说明动态多态的底层实现原理。 虚析构函数:强调基类应声

今天比昨天更努力一点! 1万+

虚函数纯虚函数区别联系

文章目录一、虚函数1. 定义二、纯虚函数1.定义三、区别联系 一、虚函数 1. 定义 在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数用法格式为: virtual 函数返回类型 函数名(参数表) {函数体}; 实现多态性,通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数。 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数虚函数的作用,用专...

江南蜡笔小新 4095

C++ 纯虚函数 虚函数 override

override在C++中它是覆盖了一个方法并且对其重写,从而达到不同的作用。在我们C++编程过程中,最熟悉的就是对接口方法的实现,在接口中一般只是对方法进行了声明,而我们在实现时,就需要实现接口声明的所有方法。还有一个典型应用就是在继承中也可能会在子类覆盖父类的方法。 1.公有继承 包含两部分:一是“接口”(interface),二是 “实现” (implementation)。 class Shape { public: virtual void Draw() const = 0;

软件工程小施同学 的专栏 3872

虚函数纯虚函数 -区别

构造函数不定义为虚函数构造函数是在实例化对象的时候进行调用,如果此时将构造函数定义成虚函数,需要通过访问该对象所在的内存空间才能进行虚函数的调用(因为需要通过指向虚函数表的指针调用虚函数表,虽然虚函数表在编译时就有了,但是没有虚函数的指针,虚函数的指针只有在创建了对象才有),但是此时该对象还未创建,便无法进行虚函数的调用。所以构造函数不能定义成虚函数。析构函数定义成虚函数

weixin_48434590的博客 3332

纯虚函数虚函数区别

纯虚函数虚函数都是使用virtual关键字,只是纯虚函数在函数原型后面加上“=0”。 含有纯虚函数的类是抽象类,不能实例化/生成对象,只能派生,它派生的类的纯虚函数如果没有重写,那么,它的派生类也是抽象类。定义纯虚函数就是为了让基类不能实例化,因为实例化这样的抽象数据结构是没有意义的(比如:熊猫、老虎、长颈鹿的基类:动物,实例化动物没有意义) 纯虚函数可以有函数体,但必须定义在类的外部。 虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现。子类可以重写父类的虚函数实现子

xihahakkk的博客 4679

C++学习——虚函数

今天来总结C++语言中极为重要的知识点——虚函数,包含常考面试题┗|`O′|┛ 嗷~~,一起来学习吧~

mingyuexin235的博客 3169

纯虚函数

纯虚函数 在基类中仅仅给出声明,不对虚函数实现定义,而是在派生类中实现。这个虚函数称为纯虚函数普通函数如果仅仅给出它的声明而没有实现它的函数体,这是编译不过的。纯虚函数没有函数体,纯虚函数需要在声明之后加个=0; 定义格式 : class <基类名> { virtual <类型><函数名>(<参数表>)=0; ...... }; 存在纯虚函数的类我们称为抽象类 含有纯虚函数的类被称为抽象类。抽象类只能作为派生类的基类,不能定

weixin_43313046的博客 3788

虚函数纯虚函数、重载函数的作用区别

虚函数为了重载多态的需要,在基类中是有定义的,即便定义是空,所以子类中可以重写也可以不写基类中的此函数! 纯虚函数在基类中是没有定义的,必须在子类中加以实现,很像java中的接口函数! 虚函数 引入原因:为了方便使用多态特性,我们常常需要在基类中定义虚函数。 class Cman { public: virtual void Eat(){……};

xiaoshengyige的专栏 4481

C++】抽象类虚基类,虚函数纯虚函数

3.带纯虚函数的类叫虚基类,这种基类不能直接生成对象,而只有被继承,并重写虚函数后,才能使用,也叫抽象类,抽象类虚继承基类还是有区别的,在C#中用abstract定义抽象类,在c++中有抽象类的概念,但是没有这个关键字。,其实在函数的前面加virtual是很好的,虽然牺牲了一些函数的性能,但是增加了面向对象的多态性,因为很难预料父类里面的这个函数不会在子类中去修改它的实现。1.类里面声明了虚函数虚函数是可以定义的,还可以空定义。在一个抽象类中,只有方法类的集合,即只有纯虚函数的列就叫做接口。

weixin_52958292的博客 2464

C++普通函数,虚函数纯虚函数区别

1.虚函数(impure virtual)   C++虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现。   子类可以重写父类的虚函数实现子类的特殊化。   如下就是一个父类中的虚函数: class A { public: virtual void out2(string s) { cout&lt...

Z685455的博客 432

C++核心机制深度解析(五):虚函数纯虚函数完全指南

虚函数纯虚函数C++实现运行时多态的核心机制,也是面向对象设计中接口实现分离的基础。本文将全面讲解虚函数纯虚函数的定义、区别、使用场景,以及它们在抽象类、接口设计中的应用。虚函数:在基类中使用virtual关键字声明的成员函数,可以在派生类中被重写,实现运行时多态。public:// 虚函数:有默认实现,但允许派生类重写// 普通函数:不能被重写public:// 重写虚函数" << endl;// 可以选择不重写,使用基类版本。

✨ 欢迎来到【Seal ^_^ 的CSDN博客】!✨ 343

C++纯虚函数普通虚函数的深度解析

纯虚函数普通虚函数C++面向对象设计中各司其职。纯虚函数强制接口实现,建立严格的类型契约;普通虚函数提供灵活扩展点,支持代码复用。理解它们的区别适用场景,是设计可维护、可扩展的C++类层次结构的基础。在实际工程中,通常会将两者结合使用,既保证必要的接口约束,又提供合理的默认行为。

T20151470的博客 761
上一篇: vector中删除的注意事项
下一篇: 虚函数和纯虚函数的作用与区别
线上幽灵
博客等级 码龄10年 338粉丝 136原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值