如何用C++实现“虚拟模板功能”

2023-11-29

首先:我已经阅读过并且现在知道虚拟模板成员函数在 C++ 中(还?) 不可能。解决方法是使类成为模板,然后在成员函数中也使用模板参数。

但在 OOP 的背景下,我发现如果该类实际上是一个模板,下面的示例就不会很“自然”。请注意,该代码实际上不起作用,但 gcc-4.3.4 报告:error: templates may not be ‘virtual’

#include <iostream>
#include <vector>

class Animal {
    public:
        template< class AMOUNT >
        virtual void eat( AMOUNT amount ) const { 
            std::cout << "I eat like a generic Animal." << std::endl; 
        }
        virtual ~Animal() { 
        }
};

class Wolf : public Animal {
    public:
        template< class AMOUNT >
        void eat( AMOUNT amount) const { 
            std::cout << "I eat like a wolf!" << std::endl; 
        }
        virtual ~Wolf() { 
        }
};

class Fish : public Animal {
    public:
        template< class AMOUNT >
        void eat( AMOUNT amount) const { 
            std::cout << "I eat like a fish!" << std::endl; 
        }
        virtual ~Fish() { 
        }
};

class GoldFish : public Fish {
    public:
        template< class AMOUNT >
        void eat( AMOUNT amount) const { 
            std::cout << "I eat like a goldfish!" << std::endl; 
        }
        virtual ~GoldFish() { 
        }
};

class OtherAnimal : public Animal {
        virtual ~OtherAnimal() { 
        }
};

int main() {
    std::vector<Animal*> animals;
    animals.push_back(new Animal());
    animals.push_back(new Wolf());
    animals.push_back(new Fish());
    animals.push_back(new GoldFish());
    animals.push_back(new OtherAnimal());

    for (std::vector<Animal*>::const_iterator it = animals.begin(); it != animals.end(); ++it) {
        (*it)->eat();
        delete *it;
    }

    return 0;
}

所以创建一个“Fishfoo”有点奇怪。然而,我似乎希望为每只动物提供任意数量的食物。

因此,我正在寻找一个关于如何实现类似目标的解决方案

Fish bar;
bar.eat( SomeAmount food );

当查看 for 循环时,这变得特别有用。人们可能想给所有不同的动物喂食特定数量(FoodAmount)(例如通过 eat() 和 bind1st()),但这并不容易做到,尽管我觉得这非常直观(因此在某种程度上) “自然”)。虽然现在有些人可能想争辩说这是由于向量的“统一”特征造成的,但我认为/希望应该可以实现这一目标,而且我真的很想知道如何实现,因为这是困扰我好一段时间了……

[EDIT]

也许为了澄清我的问题背后的动机,我想编写一个 Exporter 类并让不同的、更专业的类从中派生。虽然顶级 Exporter 类通常仅用于装饰/结构目的,但派生了 GraphExporter 类,它应该再次作为更专业导出的基类。但是,与 Animal 示例类似,我希望能够在专用/派生类(例如在 SpecialGraphExplorer 上)上定义 GraphExporter*,但在调用“write( out_file )”时,它应该为 SpecialGraphExporter 调用适当的成员函数GraphExporter::write(out_file)。

也许这让我的处境和意图更加清晰。

Best,

Shadow


经过一番思考,我认为这是经典多方法要求,即根据运行时类型多个参数。常见的虚函数有single dispatch相比之下(他们调度的类型this only).

请参考以下内容:

  • Andrei Alexandrescu has written (the seminal bits for C++?) on implementing multi-methods using generics in 'Modern C++ design'
    • 第11章:“多种方法”- 它实现了基本的多方法,使它们对数(使用有序类型列表),然后一直到恒定时间多方法。相当强大的东西!
  • A codeproject article that seems to have just such an implementation:
    • 不使用任何类型的类型转换(动态、静态、重新解释、const 或 C 风格)
    • 不使用 RTTI;
    • 不使用预处理器;
    • 强类型安全;
    • 单独编译;
    • 多方法执行的恒定时间;
    • 多方法调用期间没有动态内存分配(通过 new 或 malloc);
    • 不使用非标准库;
    • 仅使用标准 C++ 功能。
  • C++ 开放方法编译器、彼得·皮克鲍尔、尤里·索洛德基和比亚尼·斯特鲁斯特鲁普
  • 洛基图书馆有多调度程序
  • 维基百科有一个相当不错的简单的写法包含有关 C++ 中的多重调度的示例。

以下是维基百科文章中的“简单”方法供参考(不太简单的方法对于大量派生类型可以更好地扩展):

// Example using run time type comparison via dynamic_cast

struct Thing {
    virtual void collideWith(Thing& other) = 0;
}

struct Asteroid : Thing {
    void collideWith(Thing& other) {
        // dynamic_cast to a pointer type returns NULL if the cast fails
        // (dynamic_cast to a reference type would throw an exception on failure)
        if (Asteroid* asteroid = dynamic_cast<Asteroid*>(&other)) {
            // handle Asteroid-Asteroid collision
        } else if (Spaceship* spaceship = dynamic_cast<Spaceship*>(&other)) {
            // handle Asteroid-Spaceship collision
        } else {
            // default collision handling here
        }
    }
}

struct Spaceship : Thing {
    void collideWith(Thing& other) {
        if (Asteroid* asteroid = dynamic_cast<Asteroid*>(&other)) {
            // handle Spaceship-Asteroid collision
        } else if (Spaceship* spaceship = dynamic_cast<Spaceship*>(&other)) {
            // handle Spaceship-Spaceship collision
        } else {
            // default collision handling here
        }
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何用C++实现“虚拟模板功能” 的相关文章

  • 获取VirtualStore中存储的日志文件的真实路径

    我的应用程序将日志文件存储在一个位置 根据管理设置 该位置可以重定向到 VirtualStore 中的文件夹 例如 它们有时最终会出现 日志文件位于 C Users my username AppData Local VirtualStor
  • 来自 RAZOR 中不同文件夹的 RenderPartial

    我一直在尝试将我的 aspx 页面转换为 cshtml 并且在从另一个文件夹渲染部分页面时遇到问题 我以前做过的事 我认为等价的是 Html RenderPartial Views Inquiry InquiryList cshtml Mo
  • C++:初始化结构体并设置函数指针

    我正在尝试使用函数指针初始化结构 但是除非使用全局函数完成 否则我很难这样做 以下代码有效 float tester float v return 2 0f v struct MyClass Example typedef float My
  • 如何利用磁盘 IO 队列

    我需要从 3 7 GB 文件中读取小数据序列 我需要阅读的职位是不相邻 但我可以命令 IO 以便从头到尾读取文件 该文件存储在 iSCSI SAN 上 该 SAN 应该能够处理 优化排队 IO 问题是 如何一次性请求我需要的所有数据 位置
  • 通过 Office API 将多个 Word 文档保存为 HTML

    我有大量的Word文档需要解析 由于它们都是从同一个模板创建的 我认为最好的方法是将它们保存为 HTML 文件并解析 HTML 本身 虽然将单个 Word 文档保存为 HTML 相当容易 但我还没有找到从 Word 内部执行批量过程的方法
  • 将一个文件写入.c中的另一个文件

    我有一个读取文件然后将其内容复制到另一个文件的代码 我需要使其仅复制每 20 个符号 然后跳过 10 个符号 然后再次跳过 20 个符号 依此类推 我必须使用 lseek 函数 但我不知道如何将所有这些放入循环中来执行此操作 main ar
  • 用于生成 C++ 代码轮廓/图的工具 - 有这样的东西吗? [复制]

    这个问题在这里已经有答案了 我需要深入研究用 C 编写的软件组件并对其进行一些修改 我幻想生成一些代码映射 它将显示类之间的关系并引导我完成方法的流程 调用图 有这个工具吗 几年前 我使用 Rational Rose 建模工具 该工具具有对
  • web请求超时处理?

    HttpWebRequest request HttpWebRequest WebRequest Create url request Timeout 20000 using WebResponse response request Get
  • 从 C++ 中的 std::string 获取字节

    我正在一个 C 非托管项目中工作 我需要知道如何获取像 一些要加密的数据 这样的字符串并获取一个 byte 数组 我将用它作为加密的源 在 C 中我做 for int i 0 i lt text Length i buffer i byte
  • 如何使用 Moq 模拟 Web 服务调用?

    The using下面点击了我不想实际点击的外部资源 我想测试someResult以及使用它的代码 但每次我运行单元测试时 该代码仍然尝试访问真正的 Web 服务 如何使用最小起订量来伪造对 Web 服务的真实调用 但不模拟使用中的其余代码
  • 如何BSWAP 64位寄存器的低32位?

    我一直在寻找如何将 BSWAP 用于 64 位寄存器的低 32 位子寄存器的答案 例如 0x0123456789abcdef位于 RAX 寄存器内 我想将其更改为0x01234567efcdab89用一条指令 因为性能 所以我尝试了以下内联
  • 如何使用SQL Server CE的动态连接字符串?

    我在 Windows 应用程序中使用 SQL Server CE 4 0 并使用实体框架创建它的模型 它工作正常 但我的问题是它没有构造函数来更改连接字符串 并且默认情况下它从app config file using var Contex
  • WPF 应用程序在每个系统规模上具有相同的大小(与规模无关)

    有没有办法让 WPF 应用程序在每个系统规模上获得相同的大小 当我改变时更改文本 应用程序和其他项目的大小在windows系统设置中125 推荐 to 100 在全高清屏幕中 我的 WPF 应用程序变得太小 为了实现独立的系统缩放应用程序
  • OpenGL 中连续暂停

    void keyPress unsigned char key int x int y int i switch key case f i 3 while i x pos 3 sleep 100 glutPostRedisplay 上面是在
  • Eclipse 调试模式下的 GDB 找不到 stdlib/rand.c

    我试图让 gdb 在 ubuntu 上与 eclipse cdt 一起运行 以开始调试一些简单的程序 所以我做了我认为必要的步骤来让它运行 1 创建可执行项目 2 Compile 3 Run 4 创建文件 gdbinit 并将其放在主项目文
  • 如何使用 html 敏捷包获取自定义标签?

    需要创建摘要 索引 为此我有标签
  • 文件/文件夹结构的递归搜索

    我正在尝试为返回文件和文件夹列表的 Web 服务构建递归搜索功能 我创建了这两个方法 因此它们充当递归搜索 它首先获取顶级内容 然后将任何文件添加到 fileList 并将任何子文件夹添加到 subFoldersList 我们传入访问级别
  • 检测 Windows 重新启动是否是由于 Windows 更新造成的

    我的电脑上的一些应用程序一直在检测 Windows 更新是否重新启动 这是可以观察到的 因为它们会在 Windows 更新自动重启后重新启动 这非常有帮助 因为这些应用程序会重新加载更改 甚至unsaved更改或恢复选项卡 如果是浏览器 执
  • K&R 之后用什么书来学习纯 C 编程? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • .NET Web API - 添加日志记录

    我正在寻找有关处理 API 日志记录的最佳方法的帮助 我想将所有请求和响应记录到 sql 或文本文件 如果这是最好的方法 目前我已经在 SQL Server 的日志表中插入一行 我使用名为 LogAction 的静态方法来执行此操作 并在

随机推荐

  • 在 IE11 中使用数据 URL 打开 pdf.js

    我正在尝试使用 pdf js 在 IE10 上的数据 URL 中显示文档 那是 像这样的东西 它在 Firefox 或 Chrome 中运行良好 但在 Internet Explorer 10 和 11 中 会显示界面 但保持空白 并且文档
  • 在单个列表中列出所有文件夹中的所有文件

    我正在寻找列出 root Android 设备中所有文件的解决方案 假设根目录中有三个文件夹 但我想在一个列表中显示所有这些文件夹中的所有文件 现在如果我使用 File f new File sdcard 然后它会列出来自的所有文件sdca
  • 如何在 tasm 中在屏幕上打印 SVGA 信息?

    我是组装和图形的初学者 任何帮助将不胜感激 我得到了 svga 信息 但是当我打印它时 它不会打印任何内容 如果有人能解释为什么那就太好了 这是代码 如果我所做的事情需要更多解释 请告诉我 MODEL SMALL STACK 64 DATA
  • 如何将传单路由机包含到 Angular 2 TypeScript Webpack 应用程序中

    我使用这个种子开始使用 Angular 2 Typescript 和 Webpack https github com haoliangyu angular2 leaflet starter 我对大多数使用的工具和技术 Angular 2
  • 三星智能电视覆盖(新闻行情)应用程序

    有什么方法可以让应用程序作为 DVB 节目 即直播 上的覆盖 股票代码 运行 据我们所知 目前将应用程序显示为屏幕部分覆盖的唯一有效解决方案是从 TV SmartHub 菜单启动应用程序并通过 IP 通常是 HLS 流显示覆盖 例如 请参见
  • 在程序运行时更改程序

    不确定这是 emacs SLIME 问题还是 CL 问题或 SBCL 问题 我听说 Lisp 的交互特性允许在程序运行时更改程序 不知道这意味着什么 我尝试了以下操作 将其放在一个单独的文件中 defparameter repl test
  • rdr 是一个“变量”,但像“方法”一样使用

    我正在尝试将此 VB NET 代码转换为 C Protected Sub BT KEM CARIAN Click ByVal sender As Object ByVal e As System EventArgs Handles BT K
  • 使用 ng-repeat 创建 AngularJS 表

    我从数据库得到以下响应 关于类数组 其中类嵌套在组中 最后嵌套在学生中 Response Id 1 Name Class 1 Location Building 1 Groups Id 1 Name GB1 Students Id 1 Na
  • 如何在 vagrant guest 中连接到基于名称的虚拟主机?

    在盒子里 我有两个虚拟主机
  • json 文件的 $http.get 总是返回 404

    我想向我的应用程序添加一个配置 JSON 文件 我已将其添加到我的项目中并尝试使用 http get 获取它 http get http localhost myProject content json success function d
  • 低音音频库开/关按钮

    在此示例中如何创建开 关音乐按钮 在 Inno Setup 安装期间播放声音 我想使用 image png 以下脚本创建一个按钮 您可以通过该按钮根据流的当前状态播放或暂停流 Setup AppName Bass Audio Project
  • 子状态机

    我有一个有 5 个州的 FSM 其中3个是通过子FSM UML模式 设计的 对于 VHDL 中的实现 恕我直言 有两种方法可以做到这一点 将它们总结为一个 这样我就有了一份包含子 FSM 的文档和一个包含一个大 FSM 的产品 与所有州建立
  • 确定 SPA 和 .NET Core 3 的角色

    我有一个使用 NET Core 3 1 的应用程序 还有一个使用由此生成的默认 React 应用程序的前端link 在 NET Core 应用程序中 我使用用户和角色设置了 Identity Server 当我使用 React 应用程序时
  • 如何迭代字典?

    我见过几种在 C 中迭代 字典的不同方法 有标准的方法吗 foreach KeyValuePair
  • 当我使用会话将值从一个页面发送到另一个页面时,出现以下错误[重复]

    这个问题在这里已经有答案了 警告 session start 打开 var cpanel php sessions ea php56 sess c84fdb91458e26c7325faf74a529a3 O RDWR 失败 没有这样的文件
  • 获取perl字符串计算结果

    如果一个字符串如下所示 str 5 2 1 我想从该字符串中获取计算结果 如何转换为标量来计算它 谢谢 最简单的方法是 print eval 5 2 1 但这并不安全 print eval print You are hacked 您需要先
  • Laravel - 使用 whereHas 获取最后一行

    我正在尝试获取上次用户活动的时间 created at 我有模型User and UserActivity 我想获取最后一个用户活动并检查该用户的最后一个活动是否是 3 天发送通知 User php
  • 忍者。对内部设置属性的奇怪拦截

    域对象 目标对象 cs public class TargetObject public virtual ChildTargetObject ChildTargetObject get return ChildTargetObjectInn
  • python: 为什么使用子进程调用 echo 会返回 WindowsError 2?

    在我的程序中 我有一个函数 runScript def runScript subprocess call echo hello 我在 Python 文档中看到过很多类似的例子 所以我认为这可行 但是 当我在程序中调用此函数时 它返回 Wi
  • 如何用C++实现“虚拟模板功能”

    首先 我已经阅读过并且现在知道虚拟模板成员函数在 C 中 还 不可能 解决方法是使类成为模板 然后在成员函数中也使用模板参数 但在 OOP 的背景下 我发现如果该类实际上是一个模板 下面的示例就不会很 自然 请注意 该代码实际上不起作用 但