How to Check If an Object's Type Is a Particular Subclass in C++

How do I check if an object's type is a particular subclass in C++?

You really shouldn't. If your program needs to know what class an object is, that usually indicates a design flaw. See if you can get the behavior you want using virtual functions. Also, more information about what you are trying to do would help.

I am assuming you have a situation like this:

class Base;
class A : public Base {...};
class B : public Base {...};

void foo(Base *p)
{
if(/* p is A */) /* do X */
else /* do Y */
}

If this is what you have, then try to do something like this:

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();
}

Edit: Since the debate about this answer still goes on after so many years, I thought I should throw in some references. If you have a pointer or reference to a base class, and your code needs to know the derived class of the object, then it violates Liskov substitution principle. Uncle Bob calls this an "anathema to Object Oriented Design".

How do I check if a Class is a Subclass in C#?

Every class in C# is derived from Object, so it means to check if given class is subclass or not you can check Baseclass Property of type. snippet given below.

class Base {
}
class Derived : Base
{
}

now if you check

var isBase = typeof(Base).BaseType == typeof(Object) // true
isBase = typeof(Derived).BaseType == typeof(Object) // false

What is the best way to check if a subclass is of a specific type?

Have an abstract function on the Person class called something like "ReturnValidSectionsForPerson()". In each subclass, override that function to return "UserData" or "CardHolder" as appropriate. You can use an enumeration to hold the various types of sections to make it easier to read and maintain.

Know the class of a subclass in C++

You almost certainly don't want to know. What you should do is declare as virtual appropriate methods to interact with these animals.

If you need to operate on them specifically, you can either use the visitor pattern to pass a visitor object or function the right data in each concrete class. If you insist on having tags (and I emphasise that this is the third choice - the other two solutions will leave your code much cleaner), have a virtual method called classname which returns the type identifier (whether as a string or int or whatever).

Note also the point about slicing if you have an array of object type, as opposed to pointer type. If you haven't used C++ in 7 years, you may not be aware of the growth of template usage to make the language vastly better. Check out libraries like boost to see what can be done, and how templating allows you to write type-inferred generic code.

How do I check if a type is a subtype OR the type of an object?

Apparently, no.

Here's the options:

  • Use Type.IsSubclassOf
  • Use Type.IsAssignableFrom
  • is and as

Type.IsSubclassOf

As you've already found out, this will not work if the two types are the same, here's a sample LINQPad program that demonstrates:

void Main()
{
typeof(Derived).IsSubclassOf(typeof(Base)).Dump();
typeof(Base).IsSubclassOf(typeof(Base)).Dump();
}

public class Base { }
public class Derived : Base { }

Output:

True
False

Which indicates that Derived is a subclass of Base, but that Baseis (obviously) not a subclass of itself.

Type.IsAssignableFrom

Now, this will answer your particular question, but it will also give you false positives. As Eric Lippert has pointed out in the comments, while the method will indeed return True for the two above questions, it will also return True for these, which you probably don't want:

void Main()
{
typeof(Base).IsAssignableFrom(typeof(Derived)).Dump();
typeof(Base).IsAssignableFrom(typeof(Base)).Dump();
typeof(int[]).IsAssignableFrom(typeof(uint[])).Dump();
}

public class Base { }
public class Derived : Base { }

Here you get the following output:

True
True
True

The last True there would indicate, if the method only answered the question asked, that uint[] inherits from int[] or that they're the same type, which clearly is not the case.

So IsAssignableFrom is not entirely correct either.

is and as

The "problem" with is and as in the context of your question is that they will require you to operate on the objects and write one of the types directly in code, and not work with Type objects.

In other words, this won't compile:

SubClass is BaseClass
^--+---^
|
+-- need object reference here

nor will this:

typeof(SubClass) is typeof(BaseClass)
^-------+-------^
|
+-- need type name here, not Type object

nor will this:

typeof(SubClass) is BaseClass
^------+-------^
|
+-- this returns a Type object, And "System.Type" does not
inherit from BaseClass

Conclusion

While the above methods might fit your needs, the only correct answer to your question (as I see it) is that you will need an extra check:

typeof(Derived).IsSubclassOf(typeof(Base)) || typeof(Derived) == typeof(Base);

which of course makes more sense in a method:

public bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant)
{
return potentialDescendant.IsSubclassOf(potentialBase)
|| potentialDescendant == potentialBase;
}

How to find if an object is from a class but not superclass?

typeof(SpecifiedClass) == obj.GetType()


Related Topics



Leave a reply



Submit