Cha*_*had 61 c++ class subclass identification
我正在考虑使用typeid()但我不知道如何询问该类型是否是另一个类的子类(顺便说一下,它是抽象的)
Mar*_*ork 100
class Base
{
public: virtual ~Base() {}
};
class D1: public Base {};
class D2: public Base {};
int main(int argc,char* argv[]);
{
D1 d1;
D2 d2;
Base* x = (argc > 2)?&d1:&d2;
if (dynamic_cast<D2*>(x) == nullptr)
{
std::cout << "NOT A D2" << std::endl;
}
if (dynamic_cast<D1*>(x) == nullptr)
{
std::cout << "NOT A D1" << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
Dim*_*ima 42
你真的不应该.如果您的程序需要知道对象是什么类,那通常表明存在设计缺陷.看看您是否可以使用虚拟功能获得所需的行为.此外,有关您尝试做什么的更多信息将有所帮助.
我假设你有这样的情况:
class Base;
class A : public Base {...};
class B : public Base {...};
void foo(Base *p)
{
if(/* p is A */) /* do X */
else /* do Y */
}
Run Code Online (Sandbox Code Playgroud)
如果这是你所拥有的,那么尝试做这样的事情:
class Base
{
virtual void bar() = 0;
};
class A : public Base
{
void bar() {/* do X */}
};
class B : public Base
{
void bar() {/* do Y */}
};
void foo(Base *p)
{
p->bar();
}
Run Code Online (Sandbox Code Playgroud)
编辑:由于关于这个答案的辩论在这么多年后仍然存在,我想我应该引用一些参考文献.如果你有一个指针或对基类的引用,并且你的代码需要知道对象的派生类,那么它违反了Liskov替换原则.鲍勃叔叔称之为" 面向对象设计的诅咒 ".
Dre*_*all 22
你可以这样做dynamic_cast(至少对于多态类型).
实际上,在第二个想法 - 你不能告诉它是否特定类型与 - dynamic_cast但你可以告诉它是否是那种类型或其任何子类.
template <class DstType, class SrcType>
bool IsType(const SrcType* src)
{
return dynamic_cast<const DstType*>(src) != nullptr;
}
Run Code Online (Sandbox Code Playgroud)
下面的代码演示了 3 种不同的方法:
#include <iostream>
#include <typeinfo>
#include <typeindex>
enum class Type {Base, A, B};
class Base {
public:
virtual ~Base() = default;
virtual Type type() const {
return Type::Base;
}
};
class A : public Base {
Type type() const override {
return Type::A;
}
};
class B : public Base {
Type type() const override {
return Type::B;
}
};
int main()
{
const char *typemsg;
A a;
B b;
Base *base = &a; // = &b; !!!!!!!!!!!!!!!!!
Base &bbb = *base;
// below you can replace base with &bbb and get the same results
// USING virtual function
// ======================
// classes need to be in your control
switch(base->type()) {
case Type::A:
typemsg = "type A";
break;
case Type::B:
typemsg = "type B";
break;
default:
typemsg = "unknown";
}
std::cout << typemsg << std::endl;
// USING typeid
// ======================
// needs RTTI. under gcc, avoid -fno-rtti
std::type_index ti(typeid(*base));
if (ti == std::type_index(typeid(A))) {
typemsg = "type A";
} else if (ti == std::type_index(typeid(B))) {
typemsg = "type B";
} else {
typemsg = "unknown";
}
std::cout << typemsg << std::endl;
// USING dynamic_cast
// ======================
// needs RTTI. under gcc, avoid -fno-rtti
if (dynamic_cast</*const*/ A*>(base)) {
typemsg = "type A";
} else if (dynamic_cast</*const*/ B*>(base)) {
typemsg = "type B";
} else {
typemsg = "unknown";
}
std::cout << typemsg << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
上面的程序打印如下:
type A
type A
type A
Run Code Online (Sandbox Code Playgroud)
dynamic_cast可以确定类型是否包含继承层次结构中任何位置的目标类型(是的,它是一个鲜为人知的特性,如果B继承自A和C,它可以A*直接转换为a C*).typeid()可以确定对象的确切类型.但是,这两者都应该非常谨慎地使用.如前所述,您应始终避免动态类型识别,因为它表明存在设计缺陷.(另外,如果你知道对象是为确保目标的类型,你可以做一个垂头丧气了static_cast.加速提供了一个polymorphic_downcast会做一个沮丧的用dynamic_cast和assert在调试模式下,并在释放模式将只使用一个static_cast).
I don't know if I understand your problem correctly, so let me restate it in my own words...
Problem: Given classes B and D, determine if D is a subclass of B (or vice-versa?)
Solution: Use some template magic! Okay, seriously you need to take a look at LOKI, an excellent template meta-programming library produced by the fabled C++ author Andrei Alexandrescu.
More specifically, download LOKI and include header TypeManip.h from it in your source code then use the SuperSubclass class template as follows:
if(SuperSubClass<B,D>::value)
{
...
}
Run Code Online (Sandbox Code Playgroud)
根据文档,SuperSubClass<B,D>::value如果B是 的公共基础D,或者如果B和D是相同类型的别名,则为真。
即要么D是 的子类,B要么D与 相同B。
我希望这有帮助。
编辑:
请注意,SuperSubClass<B,D>::value与某些使用 的方法不同,评估发生在编译时dynamic_cast,因此在运行时使用此系统不会受到惩罚。