繁体   English   中英

一个简单的C ++委托实现,但它“欺骗”标准。 意见?

A simple C++ delegate implementation but it 'cheats' the standard. Opinions?

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我在这里发布了实施和简短的测试/演示: http//ideone.com/CNJDi

我提出了一种C ++代理方法,这种方法与我见过的其他东西不同。 我想要解决的具体问题是有一个统一的函数指针解决方案,其中给定的实例可以是a)成员fn ptr + object ptr或b)nonmember fn ptr。 初始化委托并将其交给其他代码后,他可以动态调用它,甚至不知道它来自哪种类型的对象(通常只能通过静态引用它来自的类来调用成员函数指针。 !)。 从理论上说这很容易实现,但是C ++使得这样的事情变得更加困难。 所以我扭曲了语言以使其发挥作用。

我的实现的主要缺点是,由于成员函数指针的无效强制转换/调用,它在技术上不符合“标准”(至少,我95%肯定标准不在这里保护我......)。 但它确实适用于我在其上测试的编译器(包括Visual Studio 2012)。 我还认为,如果成员函数是由编译器以简单的方式实现的,那么它将“倾向于工作”。

我看了一些其他的实现,但对我来说,它们看起来很复杂,使用起来很笨拙。 有些人甚至依靠构建工具来生成存根函数来调用成员函数,而我只依赖于宏和模板。 我认为缺乏合适的代表是C ++的一个主要缺点,但我发现我更讨厌这种解决方法。 现在我需要决定我是否真的想要使用它,或者我只是喜欢它,因为我想到了它。

以下是您使用它的方式:

A.声明代表类型

typedef DELEGATE(float, ARGS(int, int)) Delegate1;

此宏自动声明静态和成员函数指针类型,因此您不必键入签名两次。 它扩展为Delegate<float (*)(int, int), float (Null::*)(int, int)> 编译器使用其中任何一个是合适的,具体取决于委托实例的初始化方式以便稍后执行调用。 编译器使用它来静态验证编码器调用提供的参数。 ARGS宏是与返回类型分离的纯语法糖:DELEGATE(float,int,int)是相同的。

B.初始化:

Delegate1 d = Delegate1(test1); // static function
Delegate1 e = Delegate1((Delegate1::MemberType)&TestClass::test2, &obj); // member

这些静态和成员函数现在存储为相同的类型! obj必须是一个指向TestClass实例的有效指针,而TestClass :: test2最好返回一个float并将(int,int)作为参数,如上所述。 这是主要的使用陷阱,编译器无法捕捉到这里所犯的错误。

C.调用: INVOKE(d, ARGS(5, 6)) (在这个例子中返回一个浮点数)尽管它的外观,这个参数列表实际上和任何C ++函数调用一样安全! 它使用上面提供的上述float(*)(int,int)签名验证参数! 它可以支持任意数量的参数,只需匹配签名即可。 如果添加太多/太少的参数,使用编译器中的错误参数类型等,则会出现友好的编译器错误。 同样,ARGS是语法糖, INVOKE(d, 5, 6)是相同的。

但如果在不批准的编译器中使用INVOKE,它可能会崩溃程序:(

我有几个问题:

  1. 任何人都可以找到任何好的编译器,我发布的实现示例无法正常工作吗?
  2. 我希望这可以完全运行,或者编译器/程序在第一次使用时翻转。 但有可能它似乎工作了一段时间然后随机崩溃?
  3. 在您看来,这看起来容易/干净吗? 或者你发现其他实现更简单? 哪个? 你能想到以某种方式提高我的语法/可用性的好方法吗?
  4. 你会用它吗? 或者我应该咬紧牙关并使用更安全但更复杂的替代解决方案?
2 个回复

为什么不在C ++ 11 / Boost中使用std :: bind? 可以使用成员函数,函数指针,lambda函数,仿函数和任何其他可调用对象。 我个人更愿意不惜一切代价避免使用预处理器和宏; 它可以使调试成为一个巨大的混乱。 Scott Meyers(Effective C ++,More Effective C ++和Effective STL的作者)也不鼓励使用预处理器。

bind的参考: http//en.cppreference.com/w/cpp/utility/functional/bind

我还考虑使用std :: function来封装各种类型,但是bind可以干净地处理几乎所有的东西。 http://en.cppreference.com/w/cpp/utility/functional/function

任何人都可以找到任何好的编译器,我发布的实现示例无法正常工作吗?

在我看来,如果代码首先不符合标准,那就无关紧要了。 如果您必须以奇怪的方式查看语言规则,那么您的代码可能不符合标准。

符合标准的代码很重要,因为虽然编译器的实现细节可能会发生变化,但结果二进制文件的观察行为却不能。 作为标准合规问题的错误比不符合标准的代码无效的错误更容易得到修复。

我希望这可以完全运行,或者编译器/程序在第一次使用时翻转。 但有可能它似乎工作了一段时间然后随机崩溃?

如果你的代码调用了未定义的行为,那么让它工作得很好,那么在最糟糕的时候失败就是标准允许的可能性。

在您看来,这看起来容易/干净吗? 或者你发现其他实现更简单? 哪个? 你能想到以某种方式提高我的语法/可用性的好方法吗?

老实说,我认为这是一团糟。 要使用你的代表,我必须使用三个不同的宏,一个显然不是可选的单独的typedef和一个C风格的强制转换。 坦率地说,使用和观察是痛苦的。

你会用它吗? 或者我应该咬紧牙关并使用更安全但更复杂的替代解决方案?

再说一次,老实说,我只会使用std::function和friends(如果你没有C ++ 11编译器,可以使用boost::function )。 即使你发现std::function更复杂,它肯定更清洁,它是标准的,并且更有能力。

1 C ++中的简单hashmap实现

我对C ++比较陌生。 在Java中,我很容易实例化和使用hashmap。 我想知道如何在C ++中以一种简单的方式来实现它,因为我看到了许多不同的实现,并且它们对我来说都不是很简单。 ...

2 LZW C ++简单实现

所以我试图用C ++做一个简单的文件压缩器/解压缩器(我的目标不是尽可能的达到最佳效果),但是我真的很困惑,因为我充满了疑问,所以这里是: 我应该使用哪种字典(我在使用地图)? 我应该存储哪种数据(我使用String / int作为键/值)? 我应该用ASCII初始化字典吗? 我看到 ...

2018-06-13 13:23:09 1 352   c++/ lzw
3 C++ 中的简单统计实现

描述 Dengklek 先生有 N 个整数。 在这些数字中,确定最大和最小的数字。 输入格式 第一行包含一个整数 N。下一行包含 N 个整数。 输出格式 一行包含 AB,其中 A 是最大的数字,B 是最小的数字。 输入示例 8 1 -1 1 10 10 6 8 4 示例输出 10 ...

4 在c ++中简单的字符串实现

我开始在c ++中编写一个非常简单的字符串类实现,这里是代码: 你可以看到我的operator +的实现是绝对错误的,实际上存在内存泄漏。 编写运算符+ =更简单,因为我可以简单地将char *与此 - &gt; _字符串连接并返回* this。 我需要有关运营商+实施的帮助。 ...

5 C ++简单迭代器实现

我有像这样的数组: 我正在寻找一个迭代器(或类似迭代器的类)来简化以下内容: 想要一种可以与不同类型的S1,S2等一起使用的清洁器。 ...

6 c++标准库容器没有实现吗?

我正在重新实现 c++ std 容器。 在“Marc Gregoire 的专业 C++”中,我读到了这句话 C++标准指定了每个容器的接口而不是实现 实现意味着只是容器中的“模板类”代码? c++标准容器库中的实现是什么? ...

7 关于C ++标准库实现

我想知道C ++标准库函数是如何实现的。 特别是,我对iostream,stdexcept,fstream,数字(累加,inner_product等),CStdlib(atoi,strtod,strtol,strtoul等)和CMath(天花板,地板,exp,sqrt,pow等)非常感兴趣等) ...

8 什么是 C++ 中的标准延迟/终结器实现?

Golang 风格的defer一般思想在这里和这里解释。 我想知道,STL(C++11,C++14,...)或者 Boost 或者其他一些库是否包含这样一个类的实现? 所以我可以直接使用它,而无需在每个新项目中重新实现它。 ...

9 C ++中二维数组的标准实现

我需要存储一些二维数据数组,这些维数是固定的,并且在运行时已知。 是否有2D等效于array&lt;T&gt;模板(在标准库中还是在boost中)? ...

10 关于C ++编程实践的意见

我有一个我写的程序,不是太大。 除了主要功能外,它还有大约15个其他功能,可以在不同时间调用各种任务。 代码在一个文件中工作得很好,就像现在一样。 但是,我想知道是否有人有任何建议是否更智能/更高效/更好的编程将这些功能放在一个不同于main的单独文件中,或者它是否甚至是重要的。 如 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2021 STACKOOM.COM