C 箴言:多态基类中将析构函数声明为虚拟

Claude Managed Agents 架构解析:Session、Harness 与 Sandbox 三层抽象 Agent 运行时(Runtime)是大模型落地企业级应用的核心中间层,其本质是将模型推理、工具调用与状态管理解耦的工程范式。随着 LLM 应用从单次问答走向多步协同任务,传统上下文驱动的会话管理已无法支撑长周期、可审计、可恢复的智能体行为。Session 作为持久化事件日志、Harness 作为无状态函数路由器、Sandbox 作为按需销毁的安全执行环境,共同构成现代 Agent Runtime 的三大支柱。这一架构不仅解决静默失败、凭证泄露、调试困难等高频痛点,更推动价值重心从基础设施层向上迁移至 Tr 阅读详情

转自:http://www.west263.com/info/html/chengxusheji/C-C--/20080224/12883.html



有很多方法能够跟踪时间的轨迹,所以有必要建立一个 TimeKeeper 基类,并为不同的计时方法建立派生类:

class TimeKeeper {
 public:
  TimeKeeper();
  ~TimeKeeper();
 ...
};

class AtomicClock: public TimeKeeper { ... };
class WaterClock: public TimeKeeper { ... };
class WristWatch: public TimeKeeper { ... };

  很多客户只是想简单地取得时间而不关心如何计算的细节,所以一个 factory 函数——返回一个指向新建派生类对象的基类指针的函数——被用来返回一个指向计时对象的指针:

TimeKeeper* getTimeKeeper(); // returns a pointer to a dynamic-
// ally allocated object of a class
// derived from TimeKeeper

  按照 factory 函数的惯例,getTimeKeeper 返回的对象是建立在堆上的,所以为了避免泄漏内存和其他资源,最重要的就是要让每一个返回的对象都能够被完全删除。

TimeKeeper *ptk = getTimeKeeper(); // get dynamically allocated object
// from TimeKeeper hierarchy

... // use it

delete ptk; // release it to avoid resource leak

  现在我们精力集中于上面的代码中一个更基本的缺陷:即使客户做对了每一件事,也无法预知程式将如何运转。

  问题在于 getTimeKeeper 返回一个指向派生类对象的指针(比如 AtomicClock),那个对象通过一个基类指针(也就是个 TimeKeeper* 指针)被删除,而且这个基类(TimeKeeper)有一个非虚的析构函数。祸端就在这里,因为 C 指出:当一个派生类对象通过使用一个基类指针删除,而这个基类有一个非虚的析构函数,则结果是未定义的。运行时比较有代表性的后果是对象的派生部分不会被销毁。假如 getTimeKeeper 返回一个指向 AtomicClock 对象的指针,则对象的 AtomicClock 部分(也就是在 AtomicClock 类中声明的数据成员)很可能不会被销毁,AtomicClock 的析构函数也不会运行。然而,基类部分(也就是 TimeKeeper 部分)很可能已被销毁,这就导致了一个古怪的“部分析构”对象。这是个泄漏资源,破坏数据结构连同消耗大量调试时间的绝妙方法。 排除这个问题很简单:给基类一个虚析构函数。于是,删除一个派生类对象的时候就有了您所期望的正确行为。将销毁整个对象,包括全部的派生类部分:

class TimeKeeper {
 public:
  TimeKeeper();
  virtual ~TimeKeeper();
  ...
};

TimeKeeper *ptk = getTimeKeeper();
...
delete ptk; // now behaves correctly

  类似 TimeKeeper 的基类一般都包含除了析构函数以外的其他虚函数,因为虚函数的目的就是允许派生类定制实现(参见 Item 34)。例如,TimeKeeper 可能有一个虚函数 getCurrentTime,在各种不同的派生类中有不同的实现。几乎任何拥有虚函数的类差不多都应该有虚析构函数。

  假如一个类不包含虚函数,这经常预示不打算将他作为基类使用。当一个类不打算作为基类时,将析构函数声明为虚拟通常是个坏主意。考虑一个表现二维空间中的点的类:

class Point { // a 2D point
 public:
  Point(int xCoord, int yCoord);
  ~Point();
 private:
  int x, y;
};

  假如一个 int 占 32 位,一个 Point 对象正好适用于 64 位的寄存器。而且,这样一个 Point 对象能够被作为一个 64 位的量传递给其他语言写的函数,比如 C 或 FORTRAN。假如 Point 的析构函数是虚拟的,情况就完全不相同了。

  虚函数的实现需要对象携带额外的信息,这些信息用于在运行时确定该对象应该调用哪一个虚函数。典型情况下,这一信息具备一种被称为 vptr(virtual table pointer,虚函数表指针)的指针的形式。vptr 指向一个被称为 vtbl(virtual table,虚函数表)的函数指针数组,每一个包含虚函数的类都关联到 vtbl。当一个对象调用了虚函数,实际的被调用函数通过下面的步骤确定:找到对象的 vptr 指向的 vtbl,然后在 vtbl 中寻找合适的函数指针。

  虚函数如何被实现的细节是不重要的。重要的是假如 Point 类包含一个虚函数,这个类型的对象的大小就会增加。在一个 32 位架构中,他们将从 64 位(相当于两个 int)长到 96 位(两个 int 加上 vptr);在一个 64 位架构中,他们可能从 64 位长到 128 位,因为在这样的架构中指针的大小是 64 位的。为 Point 加上 vptr 将会使他的大小增长 50-100%!Point 对象不再适合 64 位寄存器。而且,Point 对象在 C 和其他语言(比如 C)中,看起来不再具备相同的结构,因为其他语言缺乏 vptr 的对应物。结果,Points 不再可能传入其他语言写成的函数或从其中传出,除非您为 vptr 做出明确的对应,而这是他自己的实现细节并因此失去可移植性。

  这里的基准就是不加选择地将任何析构函数声明为虚拟,和从不把他们声明为虚拟相同是错误的。实际上,很多人总结过这条规则:当且仅当类中至少包含一个虚拟函数时,则声明一个虚析构函数。

  但是,当完全没有虚函数时,就可能和非虚析构函数问题发生撕咬。例如,标准 string 类型不包含虚函数,但是被误导的程式员有时将他当作基类使用:

class SpecialString: public std::string { // bad idea! std::string has a
... // non-virtual destructor
};

  一眼看上去,这可能无伤大雅,但是,假如在程式的某个地方因为某种原因,您将一个指向 SpecialString 的指针转型为一个指向 string 的指针,然后您将 delete 施加于这个 string 指针,您就立即被送入未定义行为的领地。

SpecialString *pss = new SpecialString("Impending Doom");

std::string *ps;
...
ps = pss; // SpecialString* => std::string*
...
delete ps; // undefined! In practice,


// *ps’s SpecialString resources
// will be leaked, because the
// SpecialString destructor won’t
// be called.

  同样的分析能够适用于任何缺少虚析构函数的类,包括全部的 STL 容器类型(例如,vector,list,set,tr1::unordered_map。假如您受到从标准容器类或任何其他带有非虚析构函数的类派生的诱惑,一定要挺住!(不幸的是,C 不提供类似 Java 的 final 类或 C# 的 sealed 类的防派生机制。) 偶尔地,给一个类提供一个纯虚析构函数能提供一些便利。回想一下,纯虚函数导致抽象类——不能被实例化的类(也就是说您不能创建这个类型的对象)。有时候,您有一个类,您希望他是抽象的,但没有任何纯虚函数。怎么办呢?因为一个抽象类注定要被用作基类,又因为一个基类应该有一个虚析构函数,又因为一个纯虚函数产生一个抽象类,好了,解决方案很简单:在您希望成为抽象类的类中声明一个纯虚析构函数。这是个例子:

class AWOV { // AWOV = "Abstract w/o Virtuals"
public:
 virtual ~AWOV() = 0; // declare pure virtual destructor
};

  这个类有一个纯虚函数,所以他是抽象的,又因为他有一个虚析构函数,所以您不必担心析构函数问题。这是个螺旋。您必须为纯虚析构函数提供一个定义:

AWOV::~AWOV() {} // definition of pure virtual dtor

  析构函数的工作方式是:最底层的派生类(most derived class)的析构函数最先被调用,然后调用每一个基类的析构函数。编译器会产生一个从派生类的析构函数对 ~AWOV 的调用,所以您不得不确实为函数提供一个函数体。假如您不这样做,连接程式会提出抗议。

  为基类提供虚析构函数的规则仅仅适用于多态基类——基类被设计用来允许派生类型通过基类的接口进行操作。TimeKeeper 就是个多态基类,因为我们期望能操作 AtomicClock 和 WaterClock 对象,甚至当我们仅有指向他们的类型为 TimeKeeper 的指针的时候。

  并非任何的基类都被设计用于多态。例如,无论是标准 string 类型,还是 STL 容器类型都被完全设计成基类,可没有哪个是多态的。一些类虽然被设计用于基类,但并非被设计用于多态。这样的类——例如Uncopyable 和标准库中的 input_iterator_tag——没有被设计成允许通过基类的接口操作派生类对象。所以他们就无需虚析构函数。

  Things to Remember

  ·多态基类应该声明虚析构函数。假如一个类有任何虚函数,他就应该有一个虚析构函数。

  ·假如不是设计用于做基类或不是设计用于多态,这样的类就不应该声明虚析构函数。


PostgreSQL 9.3三大核心特性:SSI、FDW与JSON演进解析 可序列化快照隔离(SSI)是数据库事务一致性的重要保障机制,其基于MVCC的冲突检测设计兼顾性能与严格语义;外部数据包装器(FDW)作为统一异构数据源访问的标准接口,支撑现代数据编织(Data Fabric)架构落地;而原生JSON支持则标志着关系型数据库向混合数据模型迈出关键一步。这三项技术共同构成PostgreSQL从传统OLTP向现代数据平台跃迁的基石,广泛应用于金融强一致场景、跨源实时分析及半结构化日志处理等工程实践。本文深入拆解2013年Postgres Open确立的SSI实现原理、FDW协议规 阅读详情

相关推荐

【法律领域】【合规领域】第一篇 法律合规 企业经营中的违法行为

法律安全

weixin_49199313的博客 2098

基于MATLAB的太阳能光伏电力仿真,模拟每日太阳能发电,可视化功率曲线,并通过数值积分计算总能量输出。.zip

1.版本:matlab2014a/2019b/2024b 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

C++箴言:多态基类中将析构函数声明为虚拟

zzy5177的专栏 315

【电力负荷预测】项目介绍 MATLAB实现基于BO-Transformer-LSTM贝叶斯优化算法(BO)优化Transformer-LSTM组合模型进行居民用户多步电力负荷预测(含模型描述及部分示例

内容概要:本文介绍了一个基于BO-Transformer-LSTM的组合模型,用于实现居民用户多步电力负荷预测的完整项目实例。该模型融合Transformer的全局注意力机制与LSTM的局部时序记忆能力,构建能够捕捉长时依赖与周期性特征的深度学习架构,并引入贝叶斯优化(BO)自动搜索最优超参数组合,提升预测精度与训练效率。项目涵盖从原始数据清洗、特征工程、滑动窗口样本构建、模型设计到超参数优化、反归一化及多步误差评估的全流程,强调时间顺序划分以防止信息泄露,并通过周期编码、外生变量融合等方式增强数据表达能力。文中提供了详细的MATLAB代码示例,包括数据预处理、网络搭建、贝叶斯优化配置和预测结果评估等关键步骤。 适合人群:具备一定机器学习和时间序列分析基础,熟悉MATLAB编程环境,从事电力系统预测、智能电网、负荷管理等相关领域的研究人员、工程师及研究生。 使用场景及目标:①应用于居民级或多用户聚合负荷的短期至中期多步预测(如未来24小时);②服务于配电系统运行调度、需求响应基线设定、家庭能源管理系统优化、分布式能源协调控制等实际工程场景;③为科研提供可复现的深度学习+贝叶斯优化的技术路线参考。 阅读建议:此资源以实际项目为导向,建议读者结合提供的代码逐步实现并调试模型,重点关注数据质量控制、时间特征编码、组合网络结构设计与贝叶斯优化稳定性之间的协同关系,在实践中深入理解多步预测中的误差累积机制与超参数敏感性问题。

国央企创新负责人如何通过平台实现科研成果的快速识别与转化?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

C++箴言:多态基类中将析构函数声明为虚拟zz

有很多方法可以跟踪时间的轨迹,所以有必要建立一个 TimeKeeper 基类,并为不同的计时方法建立派生类 class TimeKeeper { public:  TimeKeeper();  ~TimeKeeper(); ...};class AtomicClock: public TimeKeeper { ... };class WaterClock: public TimeKe...

weixin_33835103的博客 131

PotPlayer自用皮肤

自用 PotPlayer 皮肤,仅微调了字体大小与颜色,是按个人习惯调整,未做适配性调整。

C++箴言:接口继承和实现继承

现在,假设 XYZ 公司的财富增长了,决定引进一种新机型,Model C。Model C 在某些方面与 Model A 和 Model B 不同。特别是,它的飞行不同。   XYZ 公司的程序员在 hierarchy(继承体系)中增加了 Model C 的 class,但是由于他们匆匆忙忙地让新的机型投入服务,他们忘记了重定义 fly function: class ModelC: public

DX 1018

2-shell及常用命令-续.pdf

2-shell及常用命令-续.pdf

# 芯片良率是怎么算出来的?——从泊松到负二项分布,一个芯片测试工程师的视角

- 良率=好Die/总Die,但选错模型可能差17个百分点 - Poisson模型过于悲观,Murphy居中,**Negative Binomial才是业界标配** - 关键不是良率数字,是**跟踪聚类因子α的变化**——它能早几周预警工艺漂移 - Chiplet时代,10颗90%良率的Die封在一起,整体良率只有35%

Freezeblur的博客 652

C++箴言:用传引用给const取代传值

缺省情况下,C++ 以传值方式将对象传入或传出函数(这是一个从 C 继承来的特性)。除非你特别指定其它方式,否则函数的参数就会以实际参数(actual argument)的拷贝进行初始化,而函数的调用者会收到函数返回值的一个拷贝。这个拷贝由对象的拷贝构造函数生成。这就使得传值(pass-by-value)成为一个代价不菲的操作。例如,考虑下面这个类层级结构:  class Per

416

历史预测+LLM双杀!DriveGPT4-V2闭环驾驶配置避坑指南

本文深入探讨了DriveGPT4-V2在工程化部署中的核心挑战与解决方案。通过融合历史轨迹预测与大语言模型,该模型旨在实现更可靠的端到端自动驾驶。文章详细解析了从环境配置、多模态Token对齐、轻量控制头设计到训练优化与闭环仿真验证的全流程,为开发者提供了一份详实的避坑指南。

transformer2023的博客 384

IT文档 1

"陷阱"技术探秘──动态汉化Windows技术的分析20个VC开发小技巧3DLabel控件API层实现语音录制API更改系统菜单条目ASP.NET 的状态管理ASP.NET中上传文件到数据库ASP.NET中发送Email完整实例ASP.NET中的HTML编码和URL编码ASP.NET创建文件并写入内容ASP.NET实现HTTP方式获取功能ASP.NET实现用户在线检测的类源码ASP.NET应用中缓

iamhere1956的专栏 472

工业级24V电源保护电路深度解析:五重防护机制详解

自恢复保险丝(PPTC,Positive Temperature Coefficient)是一种过流保护元件✅可恢复:过流后自动恢复,无需更换⚡响应快:电流超标立即动作🔄多次使用:在额定范围内可反复使用第1层(F1):阻挡过流 → 物理熔断第2层(D3):吸收浪涌 → 能量泄放第3层(Q1):防止反接 → 逻辑阻断第4层(Q2/Q3):抵御过压 → 主动切断第5层(CR):平滑启动 → 时序控制设计哲学:"让每一级保护专注做好一件事"通过这篇文章,我们深入理解了:✅自恢复保险丝。

qq_58068673的博客 3571

RS485信号测量避坑指南:示波器抓包常见问题与波形分析技巧

本文详细解析了RS485信号测量中的常见问题与解决方案,包括差分信号测量基础、终端电阻配置、共模干扰处理等关键技巧。通过实测波形案例和优化建议,帮助工程师有效提升RS485通信的可靠性和抗干扰能力,适用于工业自动化、远程监测等场景。

kappa的博客 615

深入理解C# Stream设计契约与生产实践

Stream是.NET中统一抽象字节序列的核心基类,其本质并非简单管道,而是承载隐式状态、定义严格I/O契约的抽象机制。它通过CanRead/CanSeek等虚拟属性实现渐进式能力声明,以Position与Seek的共生关系体现随机访问语义,而Length、Flush等行为则因底层载体(文件/内存/网络)差异产生显著性能与异常特征。理解Stream的抽象基类定位、状态管理逻辑及异步演进(如ValueTask、PipeReader),对规避Position错乱、Length异常、Flush误用等高频线上问题至

288

14、多标签分类与卷积神经网络在医学图像处理中的应用

本文探讨了多标签分类与卷积神经网络(CNN)在医学图像处理中的应用。文章详细介绍了多标签分类的概念和挑战,以及如何通过CNN进行高效、准确的分类任务。内容涵盖模型设计、损失函数选择、数据增强技术、类别权重调整等关键技术点,并结合实际案例,如白内障手术工具检测、视网膜血管分割等,展示了CNN在医学图像分析中的强大潜力。此外,还讨论了模型优化策略及面临的挑战与解决方案。

t8u9v0的博客 192

AI工程师的Python函数与模块工程实践

在AI工程中,Python函数与模块远不止语法基础,而是决定模型性能、可复现性与系统稳定性的核心架构单元。其设计需兼顾GPU内存管理、梯度可追溯性与数据流完整性;模块组织则需按计算图拓扑和硬件资源分布划分,而非传统业务逻辑。技术价值体现在显存优化(如@torch.no_grad)、IO加速(@lru_cache)、可观测性注入及多进程安全等关键能力。典型应用场景包括PyTorch训练脚本、Hugging Face微调Pipeline、YOLOv8数据增强链路及分布式DataLoader构建。本文聚焦AI语境

weixin_34356555的博客 334

yolov26改进 | 融合改进篇 | 基于 MobileNetV4 和双向特征金字塔网络BiFPN的融合改进(全网独家首发)

本文介绍BiFPN与MobileNetV4融合改进的YOLOv26。许多模块单独使用能够涨点,但直接叠加后可能因功能重复、通道不匹配、尺度冲突而掉点,因此融合前必须理解各模块作用。MobileNetV4利用UIB与Mobile MQA构建轻量主干,提升特征提取能力;BiFPN通过可学习权重完成双向多尺度融合,强化大、中、小目标的信息交互。两者优化Backbone与Neck,功能互补、结构冲突较少。本文提供代码、配置、消融对比及Codex修改思路,MobileNetV4也可替换其他主干,便于组合实验与二次创新

Snu77的博客 241

Hermes Agent 常见报错排查与问题解决

Hermes Agent 常见报错排查指南 摘要 本文全面梳理了 Hermes Agent 使用过程中的10类常见报错,按阶段划分为安装期、运行期认证类、后端基础设施类和长任务执行类四大类,并提供了系统化的排查流程: 安装期问题:包括命令未找到和Python版本不兼容,主要检查PATH环境和Python版本是否符合要求 认证类问题:涉及API Key认证失败和速率限制,需要验证密钥配置和配额状态 基础设施问题:包含Docker报错、MCP连接失败和OAuth令牌过期,需检查相关服务状态 执行类问题:主要是上

简简单单Onlinezuozuo 1346

AI Bots让人跟随的工程机制与安全防线解析

自主智能体(AI Agent)是当前人工智能应用的核心形态,它通过感知-决策-行动-反馈的循环,持续生成内容并影响真实用户。大模型生成文本时天然存在“幻觉”和权威感,叠加系统提示词的角色设定,使AI bots能输出高度一致且具有说服力的“类信仰文本”。在工程实践中,如何约束Agent行为、建立审计日志、设计熔断机制,成为大模型内容安全的关键。本文从技术链路拆解AI bots建立信任的过程,并给出一个最小沙盒项目复现,以及生产级AI Agent的过滤、审计、熔断和排障方案,为开发者提供可落地的安全控制参考。

343

华南理工大学-大学物理实验-不良导体热导率测量

不良导体热导率测量 引言 导热系数(又叫热导率)是反映材料热性能的重要物理量。热传导是热交换的三种(热传导、对流和辐射)基本形式之一,是工程热物理、材料科学、固体物理及能源、环保等各个研究领域的课题。材料的导热机理在很大程度上取决于它的微观结构,热量的传递依靠原子、分子围绕平衡位置的振动以及自由电子的迁移。在金属中电子流起支配作用,在绝缘体和大部分半导体中则以晶格振动起主导作用。因此,某种材料的导热系数不仅与构成材料的物质种类密切相关,而且还与材料的微观结构、温度、压力及杂质含量相联系。在科学实验和工程设计

mohen_777的博客 872
上一篇: c++基类不为虚析构函数的一个风险
下一篇: linux命令技巧归纳3
RunBoying
博客等级 码龄17年 41粉丝 117原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值