Check If Class Is Derived from a Specific Class (Compile, Runtime Both Answers Available)

Check if class is derived from a specific class (compile, runtime both answers available)

I have some remarks on the proposed compile-time x runtime solutions. In addition to when they are evaluated, is_base_of and dynamic_cast have different requirements and their answers can be different.

(1) First of all (as pointed out by others) to use dynamic_cast, base and derived classes must be polymorphic (must have at least one virtual method). is_base_of doesn't require the types to be polymorphic.

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

(3) dynamic_cast and is_base_of can give different answers (or one can compile while the other doesn't) depending on the type of inheritance (public vs protected or private). For instance consider:

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;

We have

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.

Actually the last line yields a compiler error in GCC (error: 'B' is an inaccessible base of 'D2'). VS2010 does compile it (yielding just a warning similar to GCC's error message).

(4) The requirements on the classes being polymorphic can be relaxed through an exception handling trick. Consider:

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

Then we have

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.

It's worth mentionning that is_unambiguous_public_base_of is far slower than dynamic_cast and (this became more obvious after the renaming mentioned in the update below) always returns a nullptr for downcasts:

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.

A bit outdated reference on this trick is available in the following links:

Part 1, Part 2 and code

Disclaimer: the implementation of is_unambiguous_public_base_of above is just a draft to make the point and it doesn't handle const and volatile qualifications properly.

Update: In a previous version of this post is_unambiguous_public_base_of was named my_dynamic_cast and this was a source of confusion. So I renamed it to a more meaningful name. (Thanks to Jan Herrmann.)

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".

Check if a Class Object is subclass of another Class Object in Java

You want this method:

boolean isList = List.class.isAssignableFrom(myClass);

where in general, List (above) should be replaced with superclass and myClass should be replaced with subclass

From the JavaDoc:

Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter. It returns true if so; otherwise it returns false. If this Class object represents a primitive type, this method returns true if the specified Class parameter is exactly this Class object; otherwise it returns false.

Reference:

  • Class.isAssignableFrom(Class)

Related:

a) Check if an Object is an instance of a Class or Interface (including subclasses) you know at compile time:

boolean isInstance = someObject instanceof SomeTypeOrInterface;

Example:

assertTrue(Arrays.asList("a", "b", "c") instanceof List<?>);

b) Check if an Object is an instance of a Class or Interface (including subclasses) you only know at runtime:

Class<?> typeOrInterface = // acquire class somehow
boolean isInstance = typeOrInterface.isInstance(someObject);

Example:

public boolean checkForType(Object candidate, Class<?> type){
return type.isInstance(candidate);
}

How to test if one java class extends another at runtime?

Are you looking for:

Super.class.isAssignableFrom(Sub.class)

Check in compile time if someClass.class is derived from a anotherClass.class?

In code:

anotherClass.class.isAssignableFrom( someClass.class );

If you want to also check that the other class is a real class (and not an interface) add in a call to isInterface():

!anotherClass.class.isInterface() && anotherClass.class.isAssignableFrom( someClass.class );

Example:

System.out.println( Number.class.isAssignableFrom( Integer.class )); // true

Note that instanceof won't work for you because you don't have instances, only classes.

Excerpt from Javadoc for Class.isAssignableFrom:

Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter. It returns true if so; otherwise it returns false. If this Class object represents a primitive type, this method returns true if the specified Class parameter is exactly this Class object; otherwise it returns false.

How to check if a subclass is an instance of a class at runtime?

You have to read the API carefully for this methods. Sometimes you can get confused very easily.

It is either:

if (B.class.isInstance(view))

API says: Determines if the specified Object (the parameter) is assignment-compatible with the object represented by this Class (The class object you are calling the method at)

or:

if (B.class.isAssignableFrom(view.getClass()))

API says: Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter

or (without reflection and the recommended one):

if (view instanceof B)

java - Class whose name is known at compile time and which extends other class at runtime

Maybe check out ByteBuddy.

You can "make" a new class dynamically, with features that can help support your constraints:

  • Using Class.forName to load the third party proprietary class without linking to it in your code, you pass the class name as a configuration point
  • Naming strategy gives you control on the name of generated class
  • intercept(Implementation) to insert your custom code.

Example:

Class<?> dynamicType = new ByteBuddy()
.subclass(Class.forName(thatPeskyProprietaryClass))
.namingStrategy(...)
.method(ElementMatchers.named("someMethod"))
.intercept(...)
.make()
.load(getClass().getClassLoader())
.getLoaded();

Ways to detect whether a C++ virtual function has been redefined in a derived class

You can't check for override of virtual function portably.

You need to bring the knowledge to the Solver, preferably via type as opposed to run-time flag.

One (type-based) way is to check for presence or absence of a interface, via dynamic_cast.

A probably better way is to provide overloads of solve function, in your case the Solver constructor.

Probably better advice could be given if you provided a more concrete description of the problem. It does remind of typical situation where someone (1) needs to solve some problem P, (2) envisions technical approach X as a solution to P, (3) discovers that X doesn't cut it, and (4) asks how to make X work for a vague description of P, or even for some unrelated problem Q. The details of original problem P will often suggest a much better solution than X, and the problems of making X work, irrelevant to solving P.



Related Topics



Leave a reply



Submit