如何在C++ Builder中编写类似于Delphi中的"is"和"as"关键字?

4
我希望编写一个函数(或操作符,如果可能的话),它与Delphi的“is”类似。以下是Delphi示例:
 if Sender is TMenuItem then 
   TMenuItem(Sender)->Enabled = false;

因此,在C++ Builder中,这将是类似以下代码的形式:
bool Is(*p1, *p2)
{
    p = dynamic_cast<p1*>(p2);      //here we typecast TObject to TMenuItem
    if (!!p)
    {
        return true;
    }
    else return false;
}

我该如何使函数接受任何类型的p1,p2对象?


4
您是否只是想确定A是否是B的基类?如果是,可以考虑使用std::is_base_of。如果您只是想接受任意类型,请查找模板 - hlt
2
在C++中,“正确”的方法是不要测试类,而是使用虚成员函数。 - Some programmer dude
5
我不明白为什么这个问题会被踩:它表达清晰且有意义。只因为提问者想要的并不是在C++中最佳的方法,并不意味着这个问题本身就不好。 - AGN Gazer
2
@AGNGazer - 如果对于没有发表评论或回答的用户进行负面评价时,给予更高的“罚款”,并且不匿名下降投票,则SO上的许多问题将得到解决。 - Gabriel
2
不是恶评者,但这个问题似乎容易引发讨论(即我们是否应该尝试做这样的事情)。通常,如果我标记一个问题,我不觉得有必要进一步解释 - 如果我的标记有帮助,关闭原因就足够了,如果我的标记不正确,任何评论都是无效的。 - Yksisarvinen
显示剩余9条评论
1个回答

3

问:我如何使函数接受p1,p2的任何类型的对象?

答:可以使用模板,像这样:

template<typename T, typename PtrType>
bool IsA(PtrType *ptr)
{
    return dynamic_cast<T*>(ptr) != nullptr;
}

像这样使用模板函数:

A* obj = new C();
if (IsA<C>(obj))
{
        std::cout << "obj is of type C";
}

话虽如此,我建议您避免创建此类函数,原因有两个:

  1. 您可以在任何地方使用 dynamic_cast,它更符合习惯用法,并显示您为执行此类检查所付出的成本。
  2. 检查特定类型通常是设计有缺陷的迹象。有些情况下确实需要这样做,但这种情况很少见,通常我的个人观点是不应该普遍支持这种情况,而此类函数会这样做。

2
对于第二点:是的,这不是好的面向对象编程,但在这种情况下,你会得到一个声明类型为(TObject *sender)的指针,但实际上它可能是TMenuItem*TAction*,所以有时你必须进行强制转换。-- 但我完全同意在这里使用dynamic_cast是正确的方法,因为即使例如IsA<TMenuItem>(Sender)成功了,要获取功能,你仍然需要进行dynamic_cast,所以没有节省任何东西。 - Rudy Velthuis
这可能是情况 - 我没有使用过C++ Builder,这就是为什么我尽力回答问题并给出了我的个人意见。我相信我的建议仍然适用:除非绝对必要,否则避免使用动态转换。尽量将其使用限制在绝对必要的地方,以便它不会在系统中传播到处。不要创建一个函数,使其被到处使用。 - divinas
我认为风险并不是那么大。Delphi有isas,它们满足了dynamic_cast的两个用途。我几乎没有看到任何真正滥用它的代码,或者使用它渗透整个代码的情况。它只在适当和绝对必要的情况下使用。而且我见过很多Delphi代码。 - Rudy Velthuis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接