检查类是否派生自特定类(编译、运行时两个答案都可用)

新手上路,请多包涵

这样更容易解释一个例子,

 class base {
//....
}

class derived1 : public base {
//...
}

在我的库中,有一个基类的指针。库的用户必须从基类或派生类派生类,并将指针分配给该类。

如何检查用户定义的类是从哪个类派生的?

原文由 khajvah 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 899
2 个回答

我对提议的编译时 x 运行时解决方案有一些评论。除了评估时间之外, is_base_ofdynamic_cast 有不同的要求,他们的答案也可能不同。

(1) 首先(正如其他人指出的那样)使用 dynamic_cast ,基类和派生类必须是多态的(必须至少有一个 virtual 方法)。 is_base_of 不需要类型是多态的。

(2) The operands of is_base_of are both types whereas dynamic_cast needs a type (inside < > ) and an object (inside ( ) ) .

(3) dynamic_castis_base_of 可以给出不同的答案(或者一个可以编译而另一个不能编译)取决于继承的类型( public vs protectedprivate )。例如考虑:

 struct B { virtual ~B() {} }; // polymorphic, so it can be used in a dynamic_cast
struct D1 : public B {};      // polymorphic by (public)  inheritance
struct D2 : private B {};     // polymorphic by (private) inheritance

D1 d1;
D2 d2;

我们有

static_assert(std::is_base_of<B, D1>::value, "");
static_assert(std::is_base_of<B, D2>::value, "");

assert(dynamic_cast<B*>(&d1));
assert(!dynamic_cast<B*>(&d2)); // Notice the negation.

实际上最后一行在 GCC 中产生了一个编译器错误( error: 'B' is an inaccessible base of 'D2' )。 VS2010 会编译它(只产生类似于 GCC 错误消息的警告)。

(4) 通过异常处理技巧可以放宽对多态类的要求。考虑:

 struct B { };             // not polymorphic
struct D1 : public B {};  // not polymorphic
struct D2 : private B {}; // not polymorphic

D1 d1;
D2 d2;

template <typename B, typename D>
const B* is_unambiguous_public_base_of(const D* obj) {
    try {
        throw obj;
    }
    catch (const B* pb) {
        return pb;
    }
    catch (...) {
    }
    return nullptr;
}

然后我们有

static_assert(std::is_base_of<B, D1>::value, "");
static_assert(std::is_base_of<B, D2>::value, "");

assert((is_unambiguous_public_base_of<B>(&d1)));
assert(!(is_unambiguous_public_base_of<B>(&d2))); // Notice the negation.

值得一提的是, is_unambiguous_public_base_ofdynamic_cast 慢得多,并且(在下面更新中提到的重命名后,这变得更加明显)总是返回一个 nullptr 的:

 B* b1 = &d1;
assert(dynamic_cast<D1*>(b1));        // Requires D1 and B to be polymorphic.
assert(!(is_unambiguous_public_base_of<D1>(b1))); // Notice the negation.

以下链接中提供了有关此技巧的一些过时参考:

第 1 部分、 第 2 部分代码

免责声明:以上 is_unambiguous_public_base_of 的实现只是一个草案,它不能正确处理 constvolatile 资格。

更新:在这篇文章的前一个版本中, is_unambiguous_public_base_of 被命名为 my_dynamic_cast 这是造成混乱的根源。所以我把它重命名为一个更有意义的名字。 (感谢简赫尔曼。)

原文由 Cassio Neri 发布,翻译遵循 CC BY-SA 4.0 许可协议

您可以通过多种方式做到这一点。正如其他人指出的那样,最常见的是 dynamic_cast<>std::is_base_of 。后者在编译时使用,而 dynamic_cast<> 可以在运行时使用。但是,--- dynamic_cast<>在您的源类是多态的(即至少具有一个虚函数 - 它可以是方法或其析构函数)时才有效。如果不是,编译器将触发错误。

原文由 Iosif Murariu 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题