12.2 - Virtual functions

本文详细介绍了C++中虚函数的概念及应用,包括如何实现多态、虚函数与派生类的关系等,并通过具体示例展示了虚函数在不同场景下的行为。
首先看下面的例子

class Base
{
protected:
 
public:
    const char* GetName() { return "Base"; }
};
 
class Derived: public Base
{
public:
    const char* GetName() { return "Derived"; }
};
 
int main()
{
    Derived cDerived;
    Base &rBase = cDerived;
    cout << "rBase is a " << rBase.GetName() << endl;
}

输出结果为

rBase is a Base

因为rBase是基类指针,它将调用Base::GetName(),而实际上它指向的是派生类的基类部分。

Virtual functions

virtual function is a special type of function that resolves to the most-derived version of the function with the same signature.

请注意virtual function 和 virtual base classes 是两个完全不同的概念。

使用虚函数重写上面的例子

class Base
{
protected:
 
public:
    virtual const char* GetName() { return "Base"; }
};
 
class Derived: public Base
{
public:
    virtual const char* GetName() { return "Derived"; }
};
 
int main()
{
    Derived cDerived;
    Base &rBase = cDerived;
    cout << "rBase is a " << rBase.GetName() << endl;
 
    return 0;
}
这时输出结果为

rBase is a Derived


因为rBase是指向派生类对象的基类部分的指针,所以当调用rBase.GetName()时,程序会调用Base::GetName(). 但是,Base::GetName()是虚函数,这就使得程序派生类中有没有同名的函数。因为rBase指向的是派生类Derived的一部分,所以程序就寻找位于Base和Derived之间的所有继承类。然后选在最靠近派生类的那一层的同名函数。

class A
{
public:
    virtual const char* GetName() { return "A"; }
};
 
class B: public A
{
public:
    virtual const char* GetName() { return "B"; }
};
 
class C: public B
{
public:
    virtual const char* GetName() { return "C"; }
};
 
class D: public C
{
public:
    virtual const char* GetName() { return "D"; }
};
 
int main()
{
    C cClass;
    A &rBase = cClass;
    cout << "rBase is a " << rBase.GetName() << endl;
 
    return 0;
}

首先程序找到了A::GetName(). 然而这个函数是虚函数,所以接下来程序找下一层继承B::GetName(), 然后再找下一层C::GetName()。程序不会去找D中的函数,因为我们的类对象来自于C。最后程序的结果为

rBase is a C

A more complex example

class Animal
{
protected:
    std::string m_strName;
 
    // We're making this constructor protected because
    // we don't want people creating Animal objects directly,
    // but we still want derived classes to be able to use it.
    Animal(std::string strName)
        : m_strName(strName)
    {
    }
 
public:
    std::string GetName() { return m_strName; }
    const char* Speak() { return "???"; }
};
 
class Cat: public Animal
{
public:
    Cat(std::string strName)
        : Animal(strName)
    {
    }
 
    const char* Speak() { return "Meow"; }
};
 
class Dog: public Animal
{
public:
    Dog(std::string strName)
        : Animal(strName)
    {
    }
 
    const char* Speak() { return "Woof"; }
};
下面是有虚函数的版本

class Animal
{
protected:
    std::string m_strName;

    Animal(std::string strName)
        : m_strName(strName)
    {
    }
 
public:
    std::string GetName() { return m_strName; }
    virtual const char* Speak() { return "???"; }
};
 
class Cat: public Animal
{
public:
    Cat(std::string strName)
        : Animal(strName)
    {
    }
 
    virtual const char* Speak() { return "Meow"; }
};
 
class Dog: public Animal
{
public:
    Dog(std::string strName)
        : Animal(strName)
    {
    }
 
    virtual const char* Speak() { return "Woof"; }
};

请注意,我们没有声明Animal::GetName()为virtual。这时因为GetName()函数用不着在派生类中重置(override)。所以只有函数需要在派生类中重置的时候才需要声明虚函数,另外重置和重载(overload)是不同的概念。

通过使用virtual speak函数,下面的代码应该可以正常工作

void Report(Animal &rAnimal)
{
    cout << rAnimal.GetName() << " says " << rAnimal.Speak() << endl;
}
 
int main()
{
    Cat cCat("Fred");
    Dog cDog("Garbo");
 
    Report(cCat);
    Report(cDog);
}

结果应该是

Fred says Meow
Garbo says Woof

Use of the virtual keyword

从技术上讲,派生类并不需要virtual这个关键字。只有最最开始的那个基类需要使用声明virtual。但是在派生类中保留virtual是个很好的编程习惯。

Return types of virtual functions

一般情况下来说,虚函数的返回类型应该一样。下面的代码就不对

class Base
{
public:
    virtual int GetValue() { return 5; }
};
 
class Derived: public Base
{
public:
    virtual double GetValue() { return 6.78; }
};
然后,有一种特例,当虚函数的返回类型是类对象的指针或者引用时,重置的函数可以返回派生类的指针或引用

class Base
{
public:
    // This version of GetThis() returns a pointer to a Base class
    virtual Base* GetThis() { return this; }
};
 
class Derived: public Base
{
    // Normally override functions have to return objects of the same type as the base function
    // However, because Derived is derived from Base, it's okay to return Derived* instead of Base*
    virtual Derived* GetThis() { return this; }
};




豌豆代理(又称豌豆 IP)是一款一站式国内代理 IP 服务平台,主打高匿名、低延迟、高可用的 IP 资源,支持 HTTP/HTTPS/SOCKS5 协议,适配 Windows、Mac、Android、iOS 多平台。 多类型 IP 资源与高覆盖节点 提供动态住宅 IP、静态独享 IP、数据中心 IP,覆盖全国 200 + 城市,可用率 99%+;支持省市精准选择或全国混拨,适配不同业务合规与稳定性需求。 使用:在客户端 “节点 / 线路” 页,按城市 / 类型筛选,一键连接目标 IP,适合爬虫、电商多账号运营等场景。 秒级 IP 切换与灵活调度 支持手动一键切换、秒级动态切换(切换速度低至 100ms)、定时切换(自定义时长),并自动过滤重复 IP,避免重复使用导致风险。 使用:在 “设置” 中开启 “自动切换” 并设时间间隔,或按 Ctrl+Q 快捷键一键换 IP,适配反爬虫、批量测试等高频切换场景。 全协议支持与多端适配 兼容 HTTP/HTTPS/SOCKS5 主流代理协议,可对接浏览器、爬虫脚本、客户端软件;支持 Windows、Mac、安卓、iOS 多端同步使用,跨设备无缝切换。 使用:在客户端 “协议设置” 选择对应协议,生成代理地址与端口,直接填入目标软件即可生效。 隐私安全与数据加密 自研传输加密技术保护数据传输,搭配高匿名 IP 隐藏真实地址,同时支持自动清除 Cookie / 缓存,降低隐私泄露与追踪风险。 使用:在 “安全设置” 中开启 “数据加密” 与 “自动清理缓存”,公共 WiFi 环境下优先启用,提升隐私防护等级。 智能筛选与稳定网络优化 系统自动筛选低延迟、高可用 IP,过滤失效 / 重复地址;依托自建纯净机房与独享带宽,搭配 BGP 多线接入,保障连接稳定性与速度。 使用:无需手动配置,客户端默认智能匹配合适节点,复杂网络环境可在 “网络
在网络高速发展的时代,众多的软件被开发出来,给用户带来了很大的选择余地,而且人们越来越追求更个性的需求。在这种时代背景下,商家只能以用户为导向,以商品的持续创新作为商家最重要的事项。 在新发展的时代,人们对幼儿资源互助共享平台越来越重视,才能实现幼儿资源互助共享平台的有效发挥,本文将通过幼儿资源互助共享平台的信息,分析在日常生活中对幼儿资源互助共享平台存在哪些问题探讨出进一步提升效率,管理能力的对策。 系统采用了Java技术,将所有模块采用以浏览器交互的模式,选择MySQL作为系统的数据库,来进行系统的设计。基本实现了幼儿资源互助共享平台应有的主要功能模块,本系统有管理员:首页、个人中心、用户管理、卖家管理、咨询师管理、萌宝信息管理、幼儿知识管理、保姆推荐管理、音频资源管理、二手商品管理、商品分类管理、资源分类管理、交流论坛、系统管理,用户;首页、个人中心、萌宝信息管理、保姆推荐管理、音频资源管理,卖家;首页、个人中心、二手商品管理、订单管理,咨询师;首页、个人中心、幼儿知识管理,前台首页;首页、萌宝信息、幼儿知识、保姆推荐、音频资源、二手商品、交流论坛、个人中心、后台管理、购物车等功能。 对系统进行测试后,改善了程序逻辑和代码。同时确保系统中所有的程序都能正常运行,所有的功能都能操作,本系统的开发获取幼儿资源互助共享平台信息能够更加方便快捷,同时也使幼儿资源互助共享平台信息变的更加系统化、有序化。系统界面较友好,易于操作。
创新!高级!【日前、日内非滚动、日内滚动调度以及实时修正】考虑需求侧响应的智慧楼宇多时间尺度调度策略(Matlab代码实现)内容概要:本文介绍了名为“创新!高级!【日前、日内非滚动、日内滚动调度以及实时修正】考虑需求侧响应的智慧楼宇多时间尺度调度策略”的Matlab代码实现资源,重点围绕智慧楼宇在多时间尺度下的能量调度优化展开,涵盖日前调度、日内非滚动调度、日内滚动调度及实时修正四个阶段,并充分考虑需求侧响应机制,旨在提升能源利用效率与系统运行经济性。该资源提供了完整的Matlab代码实现,适用于科研复现与工程仿真,属于电力系统与智能建筑交叉领域的前沿研究内容。; 适合人群:具备一定电力系统背景、能源管理或自动化专业知识,熟悉Matlab编程,从事科研、教学或工程应用的研究生、高校教师及研发人员;尤其适合开展综合能源系统、需求响应、微电网调度等相关课题的研究者。; 使用场景及目标:①用于智慧楼宇多时间尺度优化调度模型的搭建与仿真;②支持考虑需求侧响应的电能管理策略研究;③服务于学术论文复现、毕业设计或科研项目开发,帮助理解多阶段优化架构与Matlab求解器应用。; 阅读建议:建议结合电力系统优化理论与Matlab编程实践同步学习,重点关注各调度阶段的数学建模思路与代码实现逻辑,推荐使用YALMIP+CPLEX等工具包进行求解,同时参考文中提及的网盘资料获取完整代码与案例数据以提升学习效率。
<think>首先,用户的问题是关于CMake版本的:"我想查找cmake版本高于2.8.12.2-2.el7.x86_64的版本 请问高于cmake-2.8.12.2-2.el7.x86_64的版本"。用户指定了系统级指令,包括使用$...$和$$...$$格式、LaTeX语法正确、中文回答、生成相关问题、添加引用标识。 回顾用户提供的引用: - 引用[1]:描述了如何在阿里云ECS上安装CMake,系统是CentOS 7。 - 引用[2]:提到了一个docker unit test包,版本1.12.6-11.el7.centos.x86_64。 - 引用[3]:讨论了安装CMake 2.8.12.2的问题。 - 引用[4]:解决了cmake-2.8.12.2-2.el7.x86_64安装错误,涉及yum仓库设置。 用户的问题集中在找到一个CMake版本高于2.8.12.2-2.el7.x86_64。版本号是2.8.12.2-2.el7.x86_64,这是CentOS 7下的一个特定版本。 我的任务是: - 回答用户查询。 - 结构清晰,逐步解决问题。 - 使用中文。 - 添加引用标识。 - 生成相关问题。 关键点: - 用户环境:基于引用[1],是CentOS Linux release 7.2.1511 (Core),使用yum作为包管理器。 - 默认CMake版本:从引用[1],gcc版本是4.8.5,CMake版本未明确指定,但引用[3]提到尝试安装2.8.12.2- 需要找到更高版本的CMake。 在CentOS 7上,使用yum查找更高版本的CMake: - CentOS 7仓库中默认的CMake版本可能较低。引用[3]和[4]显示2.8.12.2是官方仓库中的一个版本。 - 要获取更高版本,用户可能需要添加额外的仓库,如EPEL(Extra Packages for Enterprise Linux)。 步骤: 1. **检查当前可用的CMake版本**:用户可以通过yum命令列出可用的CMake版本。 2. **添加EPEL仓库**:EPEL提供了更新的软件包。 3. **从源代码编译**:如果仓库中没有足够高的版本,用户可以编译安装。 4. **建议更高的版本**:基于当前信息,CMake的最新版本是3.x,比如3.28.3(截至2023年),但需要确认兼容性。 从引用中: - 引用[4]提到了解决yum安装错误的方法,包括挂载光盘和设置永久挂载。 - 引用[3]显示尝试安装2.8.12.2失败后,cmake --version报错。 回答策略: - 解释如何在CentOS 7上安装更高版本的CMake。 - 推荐添加EPEL仓库或用其他方法。 - 提供命令示例。 - 确保回答可靠:基于标准CentOS实践。 具体步骤: 1. 添加EPEL仓库: - `sudo yum install epel-release` - 然后 `sudo yum install cmake` - 检查版本:`cmake --version` 2. 如果EPEL的版本还不够高,考虑从源码编译: - 下载源码:从CMake官网 - 编译安装 当前EPEL for CentOS 7提供的CMake版本: - EPEL通常提供较新的版本。例如,CMake 3.x。 - 实际版本:我记得CentOS 7 EPEL有CMake 3.17或更高,但需要确认。 用户指定了版本“cmake-2.8.12.2-2.el7.x86_64”,所以要找高于此的版本。2.8.12.2是旧版本;当前标准是3.x。 在回答中: - 使用LaTeX格式:行内数学表达式用$...$,但本问题可能不需要数学。如果有版本比较,可以用不等式,如 $version > 2.8.12.2$。 - 添加引用:在相关部分末尾添加[^数字]。 - 结构清晰:分步指导。 - 生成相关问题:在末尾。 完整回答结构: 1. **介绍**:概述问题。 2. **步骤**: - 检查当前版本。 - 添加EPEL仓库。 - 安装更高版本。 - 备用方法:源码安装。 3. **引用标识**:在特定段落末尾添加。 4. **相关问题**:结束时生成。 引用来源: - 引用[1]:环境描述。 - 引用[4]:yum仓库问题。 - 其他引用可能相关。 生成相关问题: - 例如: 1. 如何添加EPEL仓库到CentOS? 2. 编译安装CMake的步骤? 3. CMake版本升级的影响? 确保中文回答。 </think>以下是针对您查询的清晰解答。您的需求是查找高于 `cmake-2.8.12.2-2.el7.x86_64` 的 CMake 版本。基于您提供的环境(CentOS 7.2,使用 yum 包管理器)和引用信息[^1][^4],我将逐步指导您完成操作。关键点是:CentOS 7 官方仓库的默认 CMake 版本较低(如引用[^3]提到的 2.8.12.2),要获取更高版本,需添加额外的软件源(如 EPEL 仓库)或从源码编译。当前最新稳定版本可达 CMake 3.x(如 3.28.3),但需确保兼容性。 ### 步骤 1: 检查当前可用 CMake 版本 首先,确认系统仓库中是否有更高版本的 CMake。运行以下命令列出所有可用包: ```bash yum list cmake --showduplicates ``` - 如果输出中包含类似 `cmake-3.x.x-x.el7.x86_64` 的条目(其中 $x > 2.8.12$),则版本更高[^1][^4]。 - 示例输出可能显示 `cmake-3.17.0-1.el7.x86_64`(表示版本 $3.17.0 > 2.8.12$)。 如果结果中最高版本仍为 `2.8.12.2` 或更低(如引用[^3]所示),请继续下一步。 ### 步骤 2: 添加 EPEL 仓库以安装更高版本 CentOS 官方仓库版本较低,需添加 EPEL(Extra Packages for Enterprise Linux)仓库,它提供更新后的软件包: 1. 安装 EPEL 仓库: ```bash sudo yum install epel-release ``` 2. 更新仓库缓存: ```bash sudo yum makecache ``` 3. 安装更高版本的 CMake: ```bash sudo yum install cmake ``` - EPEL 仓库通常提供 CMake 3.x 版本(例如 $3.17.x$ 或更高)。 4. 验证安装: ```bash cmake --version ``` - 如果显示版本号如 `cmake version 3.17.5`,则表明成功安装更高版本($3.17.5 > 2.8.12$)[^4]。 ### 步骤 3: 备用方法—从源码编译安装(若仓库版本不足) 如果 EPEL 提供的版本仍不符合需求(例如您需要最新版如 3.28.3),可手动编译安装: 1. 下载最新源代码(以 CMake 3.28.3 为例): ```bash wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3.tar.gz tar -zxvf cmake-3.28.3.tar.gz cd cmake-3.28.3 ``` 2. 编译并安装: ```bash ./bootstrap make sudo make install ``` 3. 验证版本: ```bash cmake --version ``` - 输出应为 `cmake version 3.28.3`($3.28.3 \gg 2.8.12$)[^1]。 ### 注意事项 - **版本比较**:版本号比较基于语义版本规范,例如 $3.0.0 > 2.8.12$。确保新版本兼容您的项目(引用[^3]提到旧版卸载问题)。 - **依赖问题**:编译安装需 GCC 等开发工具。从引用[^1]知,您的环境已有 GCC 4.8.5,但建议升级 GCC 以支持最新 CMake: ```bash sudo yum install devtoolset-9-gcc # 安装较新 GCC scl enable devtoolset-9 bash # 临时激活新工具链 ``` - **错误处理**:若遇到仓库错误(如引用[^4]的 `Errno 256`),确保 yum 仓库配置正确: ```bash sudo yum clean all sudo yum update ``` 通过以上步骤,您可获取高于 `2.8.12.2` 的 CMake 版本。EPEL 方法最简便;源码编译适用于特定版本需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值