• C++ 多态虚函数常见问题


    哪些函数不能为虚函数?
    • 非类成员的普通函数
    • 静态(static)函数
    • 构造函数不能是虚函数
      • (存储角度)虚函数的vtable,是存储在对象的内存空间的。对象没有实例化,意味着内存空间还没有,所以无法找到对应的vtable;
      • (调用角度)虚函数的作用在于父类的指针或者引用,根据动态类型调用(指向)子类的成员函数。构造函数本身需要初始化实例,所以不可能通过父类指针或引用来调用,所以不可能为虚函数,即使是虚函数也没有实际意。
    • 友元函数,友元函数不属于类的成员函数,不能被继承。
    内联函数是否可以为虚函数(虚函数可以是内联函数)?
    • 虚函数可以是内联函数;
    • inline是可以修饰虚函数;
    • 编译器具有实际对象非指针或引用时可以内敛,但此时虚函数没有表现出多态性
      参考:
      虚函数可以是内联函数吗?
    析构函数是否可以为虚函数?

    可以

    虚析构函数是为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象。

    
    #include 
    #include 
    using namespace std;
    class SoftWare {
    public:
    	SoftWare(){};
    	virtual ~SoftWare() { 
    		std::cout << __FUNCTION__ << std::endl; 
    	};
    	//运行期多态
    	virtual void RunApp() { std::cout << " Interface SoftWare " << std::endl; };
    };
    
    class ChatApp : public SoftWare {
    public:
    	ChatApp(){};
    	~ChatApp() { 
    		std::cout << __FUNCTION__ << std::endl; 
    	};
    	void RunApp() { std::cout << " Start Chat APP " << std::endl; }
    };
    
    int main()
    {
    	SoftWare* app = new ChatApp();
    	std::cout << "================================" << std::endl;
    	app->RunApp();
    	delete app;
    	app = nullptr;
    	/*由于SoftWare有虚析构函数,delete释放内存会先调用派生类析构函数,再调用基类析构函数,防止内存泄漏。*/	
    	std::cout << "================================" << std::endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    虚析构函数存在的原因:
    • delete释放基类指针时,编译器会根据类型来调用类的成员函数,首先调用基类的析构函数,如果有派生类,则会根据虚表继续调用派生类的析构函数。
    • 假设基类的析构函数为非虚函数时,当释放一个基类指针指向的派生类实例时,则只清理了派生类从基类继承过来的虚函数,而派生类自己独有的资源却没有被清理。
    为什么默认的析构函数不是虚函数?

    节省内存

    类中有虚成员函数时,类会自动进行执行一些工作。包括生成虚函数表和虚表指针,这样会占用额外的内存,如果类无派生类,这种内存开销无疑是浪费;

    什么是纯虚函数?

    纯虚函数是在基类中声明的虚函数,它在基类中有定义,在派生类必须定义自己的实现方法。基类不能创建对象,可以使用指针或者引用派生类对象。语法上基类声明纯虚函数的方法,是在函数原型后加“=0”

    virtual int TestFunc() = 0;
    
    • 1
    • 含有纯虚函数的类叫抽象类,抽象类不能直接创建对象。只有被继承并重写其纯虚函数后,才能使用。
    • 抽象类被继承后,子类可以继续是抽象类,也可以是普通类
    纯虚函数存在的原因及意义?
    • 为了使用多态特性,需要在基类中定义虚拟函数,很多时候,基类本身生成对象是不合情理的。从面向接口编程出发,接口可以被实例化,这违背了“接口”本身的意义。
    • 纯虚函数存在:让所有继承抽象类的派生类都可以执行纯虚函数的动作,但抽象类不会为纯虚函数提供一个默认方法。强行让派生类实现属于自己的虚函数方法。
  • 相关阅读:
    C# .Net6 指定WSDL, 生成Webservice,调用该接口服务
    [云原生.docker安装]Centos7安装docker环境
    双机调试环境搭建 windbg + virtualkd 已完成未发布
    String的intern()方法详解
    iNeuOS工业互联网操作系统,脚本化实现设备运行时长和效率计算与统计
    基于阿里云 Serverless 快速部署 function 的极致体验
    【web-攻击用户】(9.6.1)其他客户端注入攻击:HTTP消息头、cookie
    Git开发、发布、缺陷分离模型概述(支持master/develop/feature/release/hotfix类型分支)
    (附源码)ssm高校专升本考试管理系统 毕业设计 201631
    湖仓一体技术解读|流式计算实现秒级数据入湖
  • 原文地址:https://blog.csdn.net/u013052326/article/details/127780681