- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
对于特定的类层次结构,我需要知道基类引用是否是特定派生类的实例。由于不同的原因,我不能在这里使用标准的 C++ RTTI,我需要实现一个自定义的 instanceof
机制。
LLVM-stle RTTI会满足我的需求,但我想知道是否存在一种方法(以某种方式使用模板)来自动执行 classof
方法?
是否有其他/更简单的实现这种机制可以知道基类是否是派生类的实例?
我的约束:
最佳答案
I was wondering if it would exists a way (somehow using templates) to automate the implementation of the classof method?
是的,有很多方法可以使 classof 方法自动化,我真的不明白为什么 LLVM 页面会演示一组手动滚动的 classof 方法,因为如果您将这个非常简单的过程自动化,它的可扩展性就会大得多。
这是一个非常基本的解决方案:
class TypedObject {
public:
virtual ~TypedObject() { };
virtual int getClassId() const { return 0; };
static int getStaticClassId() { return 0; };
virtual bool isOfType(int aID) const { return (aID == 0); };
template <typename T>
bool isOfClass() const { return isOfType( T::getStaticClassId() ); };
};
运行时转换(即 dynamic_cast
)函数如下所示:
template <typename T>
T* runtime_ptr_cast(TypedObject* p) {
if( (p) && (p->isOfClass<T>()) )
return static_cast<T*>( p );
return NULL;
};
template <typename T>
typename std::enable_if<
std::is_const< T >::value,
T* >::type runtime_ptr_cast(const TypedObject* p) {
if( (p) && (p->isOfClass<T>()) )
return static_cast<T*>( p );
return NULL;
};
然后,您所需要的只是宏来自动创建虚拟和静态函数:
#define MY_RTTI_SYSTEM_CREATE_TYPE_1_BASE( NEWCLASSID, BASECLASSNAME ) \
public: \
virtual int getClassId() const { return NEWCLASSID; }; \
static int getStaticClassId() { return NEWCLASSID; }; \
\
virtual bool isOfType(int aID) const { \
return ((aID == NEWCLASSID) || BASECLASSNAME::isOfType(aID)); \
};
然后,您可以像这样创建一个新类:
class Foo : public TypedObject {
// ... some code, as usual ...
// call the macro with a given ID number and the name of the base-class:
MY_RTTI_SYSTEM_CREATE_TYPE_1_BASE(1, TypedObject)
};
这导致:
int main() {
Foo f;
TypedObject* b = &f;
// check the type:
if( b->isOfClass<Foo>() )
std::cout << "b is indeed for class Foo!" << std::endl;
// make a dynamic cast:
Foo* pf = runtime_ptr_cast<Foo>( b );
if( pf )
std::cout << "cast to 'Foo*' was successful!" << std::endl;
const TypedObject* cb = b;
const Foo* cpf = runtime_ptr_cast<const Foo>( cb );
if( cpf )
std::cout << "cast to 'const Foo*' was successful!" << std::endl;
Foo* pf2 = runtime_ptr_cast<Foo>( cb ); // ERROR: no such function (invalid cast).
};
当然,您也可以将其扩展到多重继承,只需创建更多用于注册类型的宏。此方案还有无数种变体(就我个人而言,在 my implementation 中,我将类型注册到全局存储库并提供对工厂函数的访问权限)。
我认为没有任何实用的方法可以避免在您创建的每个类中使用 MACRO 调用。我已经考虑了一段时间(前段时间,当我自己做的时候)并且我得出结论,最简单和最干净的解决方案是在类中进行宏调用(尽管我非常不屑于在类中调用宏)一般的)。但我不知道,也许其他人有更好的(基于模板的)解决方案,不会造成太多困惑或不太干扰。我多年来一直在使用这个方案,它非常漂亮干净。
I don't have multiple inheritance but I have several level of inheritance.
上述方案适用于任何级别的继承(即,它是一个可扩展的解决方案)。如果有一天您愿意,它也可以很容易地适应多重继承。
Impact on memory footprint must be as minimal as possible
我知道 LLVM 更喜欢没有任何虚函数的解决方案,而是在基类中使用 integral-id 数据成员。使用这种方案实现与上述相同类型的功能变得有点困难(但可能)。使用虚函数要容易得多,它只占用一个指针(vtable 指针)的空间,通常不比一个整数 id 数据成员大多少。如果类已经是多态的,那么成本就什么都不是了。而且,当然,上面的代码比内置的 C++ RTTI 轻得多。因此,除非您真的想压缩可以使用整数 ID(或枚举)解决方案腾出的那几个字节,否则我建议您使用基于虚函数的解决方案,就像我上面展示的那样。
it is not possible to perform dynamic allocation.
一般不需要动态分配。只有更复杂(和功能更丰富)的 RTTI 实现才需要一些动态分配。如果您想要的只是能够执行“classof()”(因此,动态转换),那么肯定不需要动态内存分配。
关于c++ - 自动化 LLVM 风格的 RTTI 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15814775/
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 5 年前。 Improve t
背景 我有一个 Azure Runbook(名为 RunStoredProcedure2),定义如下: param( [parameter(Mandatory=$True)] [string] $Sq
我有一个名为“团队”的表,其中包含“非事件”列,另一个表“事件”,其中包含“时间”列。如果任何团队的“事件”中的最新日期发生在 X 时间之前,如何将“非事件”列更新(为 true)? 我知道这可以通过
下面的问题可能有点令人困惑,但我会尽力以最好的方式解释它。 假设我们为一家制造公司工作。它制造然后用于制造产品的组件。在以下示例中,有 3 个组件和 2 个最终产品。 组件和产品的需求如下: comp
我有代码可以让我在一个范围内选择一个项目: COleVariant vItems = cstrAddr; hr = AutoWrap(
我正在开发一个应用程序,该应用程序有 4 种语言的大约 50 个应用内购买,这给了我很多表单和子表单、框和子框,需要使用 iTunesConnect 的令人痛苦且设计糟糕的表单来填充。 我想知道是否有
我想在 Azure 自动化中使用 powershell 脚本来安排打开/关闭资源。 我想在不创建帐户的情况下执行此操作,因为我们的域强制重置密码。我知道自动化帐户会创建一个证书 - 当使用资源管理器(
我尝试从 azure 自动化 run book power shell 自动检索 azure SQL 数据库中的数据。我发现azure自动化帐户的模块中缺少SQL Server模块。我已经导入了该模块
我正在自动化 Outlook,并且需要控制电子邮件的发件人身份。用户将在 Outlook 中设置两个或多个帐户,我需要能够选择从哪个帐户发送电子邮件。有什么想法吗? 需要 Outlook 2003 及
我尝试从 azure 自动化 run book power shell 自动检索 azure SQL 数据库中的数据。我发现azure自动化帐户的模块中缺少SQL Server模块。我已经导入了该模块
假设我有一个网站,我可以(随时)登录并每隔 x 小时提交数据(单击登录后可见的链接),我将如何自动化此过程? 我构建了一个图形用户界面,它为用户(现在是我,为了我自己的方便)提供了一个包含一些信息的界
我正在开发一个程序,它的任务是我们为它定义一些号码(我们的一些手机号码)并且它应该在 Telegram 中注册它们,然后获取发送到该号码的所有消息。如您所知,在 Telegram 中注册需要提供电话号
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 3 年前。 Improve this qu
最近我在处理 CSS Sprite 。一切正常。 我创建了一个 sprite、.css 文件和 html 结构。看起来像 .sprites{ background-image:url
我想为一款名为 Dune 2000 的策略游戏创建一个叠加层。令人讨厌的是,要创建 10 个士兵,每次完成一个都必须单击该图标。没有队列。因此,在不干扰游戏运行方式的情况下,我想听听鼠标移动的声音,当
我是 python 的初学者,我想从自动化开始。以下是我正在尝试执行的任务。 ssh -p 2024 root@10.54.3.32 root@10.54.3.32's password: 我尝试通过
当我将一些 urlencoded Javascript 粘贴到 Firefox 和 Chrome 上的 URL 时,我看到了一些奇怪的事情发生。是否可以使用此技术告诉 Chrome 访问 URL,然后
我需要将大量请求自动提交到基于云的数据库接口(interface) (Intelex)。没有任何方法可以批量提交某些操作,但是提交单个请求所必需的只是让经过身份验证的用户尝试打开 Web 链接。因此,
假设我有一个进程的内存转储。我想对其运行报告,所以基本上我想打开 WinDBG,加载 SOS 并运行一个脚本,该脚本运行一些命令,解析输出,然后基于此运行更多命令。 除了像 SendKeys 这样的
我正在使用 ffmpeg 创建视频剪辑。我想自动化该过程并保存剪辑,而无需手动为要保存的每个文件命名。这是我拥有的代码。它将创建并保存剪辑,但只能使用扩展名和不是名字。 @echo off cd /d
我是一名优秀的程序员,十分优秀!