关于C++类中typedef函数的疑问

2024-04-05

我需要定义一个返回类对象的函数。

假设我有一个名为狗的类(.h 中的类声明和 .cpp 中的实现),当狗死时,我想调用一个函数让狗管理器知道这一点。在dog的SetFunc中我将收到要调用的函数:

Dog.h

class Dog
{
public:

    typedef void (*OndogDie)(Dog * dog);

    OndogDie function;

    void SetFunc(OndogDie func);
    void Die();
};

Dog.cpp

void Dog::SetFunc(Dog::OndogDie func)
{
    function = func;
}

void Dog::Die()
{
    function(this);
}

如果我将 typedef 放入 Dog 类中,则一切正常,但 Manager 类除外,它无法将 Dog 类的合适回调作为参数传递:

管理器.h

#include "Dog.h"

class Manager
{
public:
    Manager();
    void CbdogDie(Dog * dog);
};

管理器.cpp

void Manager::CbdogDie(Dog * d)
{
    //stuff
}

Manager::Manager()
{
    Dog d = Dog();
    d.SetFunc(CbdogDie); (Error: argument of type void(Manager::*)(Dog *d) is incompatible with parameter of type "Dog::OndogDie")
}

我已经查看了许多教程并回答了问题,但没有一个能帮助我找出代码的问题所在。我也考虑过使用委托类型,但它只适用于 clr 项目。

我认为问题可能出在我放置 typedef 函数的地方。还有其他地方可以定义这个函数吗?如果没有,有没有解决这个问题的方法,或者至少有替代方案。

Thanks


为了方便更多读者,重复我的评论:CbdogDie(在您的代码中)是一个函数成员(非静态)并且需要一个实例Manager被调用,因此其类型与您的回调不兼容typedef.

与您的错误无关,但仍然值得考虑:您不应该将调用回调的逻辑移至Dog的析构函数?在 C++ 中(例如,与 Java 不同),我们知道对象何时被破坏。

不确定您是否可以将其应用于实际问题,但这里有一些有效的示例。

#include <iostream>
#include <string>

class Dog
{
public:

  typedef void (* on_dog_die_callback_t)(const Dog&);

  Dog(const std::string& name, on_dog_die_callback_t callback) :
    name_(name), callback_(callback)
  {
    std::clog << "A new dog named " << this->getName() << " is born.\n";
  }

  ~Dog()
  {
    std::clog << "A dog named " <<  this->getName() << " has died.\n";
    if (this->callback_)  // allow NULL pointer for no-op
      this->callback_(*this);
  }

  std::string
  getName() const
  {
    return this->name_;
  }

private:

  std::string name_;
  on_dog_die_callback_t callback_;
};

// Note: This is a free function, not a class member.
void
friendly_callback(const Dog& dog)
{
  std::clog << "We are so sorry that " << dog.getName() << " died.\n";
}

struct Manager
{
  // Note: This is a static function.
  static void
  unfriendly_callback(const Dog& dog)
  {
    std::clog << "Haha, " << dog.getName() << " died.\n";
  }
};

int
main()
{
  Dog fido("Fido", friendly_callback);
  Dog leika("Leika", Manager::unfriendly_callback);
  Dog waldo("Waldo", 0);
}

运行这段代码的输出是:

A new dog named Fido is born.
A new dog named Leika is born.
A new dog named Waldo is born.
A dog named Waldo has died.
A dog named Leika has died.
Haha, Leika died.
A dog named Fido has died.
We are so sorry that Fido died.

请注意,我已经(不需要)更改了您的回调的签名以接受const参考一个Dog而不是指针。这通常被认为是更好的风格,但如果你need无论出于何种原因我看不到一个指针,你也可以做到。

Notice:如果您决定从析构函数调用回调,请注意需要注意一些不寻常的事情:

  • 在析构函数中尽早调用回调。如果你的Dog类拥有在调用回调之前在析构函数中释放的资源,您将传递一个this指向部分破坏的对象的指针并调用其上的任何成员函数可能会调用未定义的行为。
  • 回调不得调用任何virtual职能成员Dog它已经通过了。注意Dog的析构函数只会被调用after派生类的析构函数(如果有),因此它可以处理已经部分析构的对象。只要回调只对Dog基类,这很好,但是如果它尝试访问派生类的任何成员(通过virtual函数调用),将导致未定义的行为。

好消息:如果你的课程很简单(没有virtual函数,析构函数中没有显式释放资源),你会没事的。

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

关于C++类中typedef函数的疑问 的相关文章

  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • 为什么 C# Array.BinarySearch 这么快?

    我已经实施了一个很简单用于在整数数组中查找整数的 C 中的 binarySearch 实现 二分查找 static int binarySearch int arr int i int low 0 high arr Length 1 mid
  • WCF RIA 服务 - 加载多个实体

    我正在寻找一种模式来解决以下问题 我认为这很常见 我正在使用 WCF RIA 服务在初始加载时将多个实体返回给客户端 我希望两个实体异步加载 以免锁定 UI 并且我想利用 RIA 服务来执行此操作 我的解决方案如下 似乎有效 这种方法会遇到
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 秒表有最长运行时间吗?

    多久可以Stopwatch在 NET 中运行 如果达到该限制 它会回绕到负数还是从 0 重新开始 Stopwatch Elapsed返回一个TimeSpan From MSDN https learn microsoft com en us
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定

随机推荐

  • 在client和serviceWorker之间传输数据

    我想尝试在 serviceWorker 中运行 websockets 我编写了注册serviceWorker的代码 if serviceWorker in navigator navigator serviceWorker register
  • SendInput 不会将基本 Unicode 发送到某些窗口

    我在 C 中遇到这个项目的问题 当使用 WinAPI SendInput 函数时
  • Excel VBA:为什么没有添加任何后续系列?

    我试图将大约 200 个系列绘制到一个图表上 并尝试使用 for 循环为我绘制所有系列 但是 当我运行以下代码时 只有第一个系列 不在 for 循环中 实际上进入了图表 for 循环生成的所有其他内容都没有显示 我不知道为什么 Sub Ma
  • 如何禁用/启用复选框激活中的 PayPal 按钮?

    我的网站上有一个页面设置为定期付款 但我想禁用 PayPal 结账按钮 直到有人选中同意我的服务条款的框 你能帮我弄清楚如何正确地做到这一点吗 谢谢 布拉德 p class hidden Please check the checkbox
  • httplib.InvalidURL:非数字端口:

    我正在尝试编写一个脚本来检查是否存在许多网址 import httplib with open urls txt as urls for url in urls connection httplib HTTPConnection url c
  • 我如何强制浮动 DIV 匹配另一个浮动 DIV 的高度?

    我的 HTML 代码只是将页面分为两列 分别为 65 35 div style width 65 height 1 background color FDD017 div div div div style width 35 height
  • @XmlPath 在 JAXB 编组期间没有影响

    我正在尝试使用创建 XMLJaxB Marshalling方法 我想跳过某些子项的父标签 或者可能添加新的XML某个元素的父标签 因此我尝试使用 XmlPath from import org eclipse persistence oxm
  • R plyr,data.table,应用data.frame的某些列

    我正在寻找加速我的代码的方法 我正在调查apply ply方法以及data table 不幸的是 我遇到了问题 这里有一个small样本数据 ids1 lt c 1 1 1 1 2 2 2 2 ids2 lt c 1 2 3 4 1 2 3
  • 如何在运行时更改android中睡眠/定时器线程的延迟?

    我试图做的是每次计数器变为 5 的倍数时减少计时器延迟 但是 一旦代码进入 if 块 它就停止递增计时器 我不明白发生了什么事 这是代码 thread new Thread public void run try if count 5 0
  • 最小化 WPF 中的窗口?

    使用 Windows 时如何以编程方式最小化窗口WPF 我似乎可以找到 Resize 属性 set WindowState WindowState Minimized
  • ListView 中重复的行

    我知道这个问题已经出现过很多次了 但由于某种原因我似乎无法让它发挥作用 事实上 在某些情况下 getView 会被多次调用 但是 在此处给出的示例中 http android amberfog com p 296 http android
  • 如何检查 python 函数是否发生更改(在实时代码中)?

    如果我有一个函数的引用 我可以检查它的代码对象f code 获取签名 然后针对此签名执行后续检查以查看代码是否已更改 这很好 但是 如果函数的依赖项之一发生变化怎么办 例如 def foo a b return bar a b 比方说foo
  • 我应该直接访问mongodb吗?

    我们正在制作android应用程序 需要从mongodb数据库获取数据 数据库中会有很多条目 并且请求会非常频繁 我们应该直接访问它还是制作一个 PHP 脚本来访问它并以 JSON 格式返回所需的结果 我们应该直接访问它吗 You 确实不想
  • 使用knitr和RStudio在外部文件中进行代码折叠

    我找不到任何方法可以将语法上可接受的 RStudio 样式折叠插入到外部 R 代码文件中 该文件设置为从 knitr 文档中使用 或者我错过了什么 有几种方法可以做到这一点 1 允许代码标头 例如 knitr Q1 也许 knitr Q1
  • java中如何对对象进行排序? [复制]

    这个问题在这里已经有答案了 可能的重复 如何按属性对对象的数组列表进行排序 https stackoverflow com questions 2535124 how to sort an arraylist of objects by a
  • 将行恢复为默认列值 mysql

    我正在使用 MySQL 社区服务器 5 1 有没有一种方法可以通过一个查询将所有行设置回默认列值 我刚刚添加了很多行 我为大多数指定的列设置了默认值 但由于某种原因 所有列值都设置为 0 我想知道是否有一个查询将所有列值设置为其默认值 并且
  • java.lang.IllegalStateException:找不到工厂javax.faces.application.ApplicationFactory的备份[重复]

    这个问题在这里已经有答案了 我想从 jsf 2 1 迁移到 2 2 但无法运行我的服务器 Tomcat 导致出现以下错误 我谨通知您 我在项目 Maven 中使用了 Hibernate Spring JSF Root WebApplicat
  • Windows 7 中 NASM 程序中的 I/O

    我想用 NASM 汇编语言进行编程 我有 NASM 2 07 和 Borland C 编译器 5 0 bcc32 我的操作系统是Windows 7 我不知道如何在Windows平台上使用NASM进行输入和输出 请问你能帮我吗 最简单的方法是
  • 调试 javascript 有哪些好的技巧? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 所以我相当经常地使用 JavaScr
  • 关于C++类中typedef函数的疑问

    我需要定义一个返回类对象的函数 假设我有一个名为狗的类 h 中的类声明和 cpp 中的实现 当狗死时 我想调用一个函数让狗管理器知道这一点 在dog的SetFunc中我将收到要调用的函数 Dog h class Dog public typ