C++ overloading method based on derived class - c++

I am facing the following problem with my code:
#include <iostream>
using namespace std;
class Base {
public:
virtual void sayHello()=0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
};
void sayHello(Impl1 *i) {
cout << "Impl1 says: ";
i->sayHello();
}
void sayHello(Impl2 *i) {
cout << "Impl2 says: ";
i->sayHello();
}
int main()
{
Impl1 *i1 = new Impl1();
Base *b = i1;
sayHello(b);
return 0;
}
And here the compiler complains about the sayHello(b); line in the
code.
"call of overloaded 'sayHello(Base*&)' is ambiguous"
Is there a way to solve this problem?
EDIT:
I basically want to pass my object to a function that does some calculations based on the type of the object. My object intentionally lacks of information in order to make the needed calculations. So Impl1 and Impl2 just contain some basic data, without the knowledge of more data needed to do the calculations.

Overload resolution is performed at compile time. It means for sayHello(b);, the compiler only know that the type of b is Base*, it won't and can't know that b is pointing to a Impl1 object actually. Then results in ambiguous call; converting Base* to Impl1* or Impl2* is equivalent rank for the call.
PS: might be OT, but for you code sample, a function taking a Base* would work fine; dynamic dispach will take effect.
class Base {
public:
virtual void sayHello()=0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
};
void sayHello(Base *i) {
cout << "Some derived class of Base says: ";
i->sayHello();
}
int main()
{
Impl1 i1;
Impl2 i2;
Base *b = &i1;
sayHello(b); // "Hi from Impl1"
b = &i2;
sayHello(b); // "Hi from Impl2"
return 0;
}
If you need to know the dynamic type at run-time, you can use dynamic_cast. e.g.
Base *b = /* something */;
Impl1 * pi1 = dynamic_cast<Impl1*>(b);
if (pi1 != nullptr) sayHello(pi1);

Since overloads are resolved at compile time, you have to supply the compiler with the exact type in order for the overload resolution to succeed.
In order to dispatch on the type, add a virtual member function to the Base, and use it to choose the overload:
class Base {
public:
virtual void sayHello()=0;
virtual void callSayHello() = 0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
void callSayHello() {sayHello(this); }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
void callSayHello() {sayHello(this); }
};
void sayHello(Impl1 *i) {
cout << "Impl1 says: ";
i->sayHello();
}
void sayHello(Impl2 *i) {
cout << "Impl2 says: ";
i->sayHello();
}
...
b->callSayHello();
Note that implementations of callSayHello are identical, but you cannot place them into Base class, because the type of this would be different.
Note: the idea for this implementation is borrowed from C++ implementation of the Visitor Pattern.

Get rid of the two free-standing functions and call b->sayHello(); directly:
Impl1 *i1 = new Impl1();
Base *b = i1;
b->sayHello();
Or use an ugly workaround with dynamic_cast:
Impl1 *i1 = new Impl1();
Base *b = i1;
sayHello(dynamic_cast<Impl1*>(b));
The need to resort to dynamic_cast often suggests an error in the class design. This may very well be the case here. Chances are that you should never have introduced a supposedly object-oriented base class in the first place.
Note also that you do not call delete at the end. If you do, you will need a virtual destructor in Base.

Related

Handling unique methods of Subclasses

I have a component in a software that can be described by an interface / virtual class.
Which non-virtual subclass is needed is decided by a GUI selection at runtime.
Those subclasses have unique methods, for which is makes no sense to give them a shared interface (e.g. collection of different data types and hardware access).
A minimal code example looks like this:
#include <iostream>
#include <memory>
using namespace std;
// interface base class
class Base
{
public:
virtual void shared()=0;
};
// some subclasses with shared and unique methods
class A : public Base
{
public:
void shared()
{
cout << "do A stuff\n";
}
void methodUniqueToA()
{
cout << "stuff unique to A\n";
}
};
class B : public Base
{
public:
void shared()
{
cout << "do B stuff\n";
}
void methodUniqueToB()
{
cout << "stuff unique to B\n";
}
};
// main
int main()
{
// it is not known at compile time, which subtype will be needed. Therefore: pointer has base class type:
shared_ptr<Base> basePtr;
// choose which object subtype is needed by GUI - in this case e.g. now A is required. Could also have been B!
basePtr = make_shared<A>();
// do some stuff which needs interface functionality... so far so good
basePtr->shared();
// now I want to do methodUniqueToA() only if basePtr contains type A object
// this won't compile obviously:
basePtr->methodUniqueToA(); // COMPILE ERROR
// I could check the type using dynamic_pointer_cast, however this ist not very elegant!
if(dynamic_pointer_cast<A>(basePtr))
{
dynamic_pointer_cast<A>(basePtr)->methodUniqueToA();
}
else
if(dynamic_pointer_cast<B>(basePtr))
{
dynamic_pointer_cast<B>(basePtr)->methodUniqueToB();
}
else
{
// throw some exception
}
return 0;
}
Methods methodUniqueTo*() could have different argument lists and return data which is omitted here for clarity.
I suspect that this problem isn't a rare case. E.g. for accessing different hardware by the different subclasses while also needing the polymorphic functionality of their container.
How does one generally do this?
For the sake of completeness: the output (with compiler error fixed):
do A stuff
stuff unique to A
You can have an enum which will represent the derived class. For example this:
#include <iostream>
#include <memory>
using namespace std;
enum class DerivedType
{
NONE = 0,
AType,
BType
};
class Base
{
public:
Base()
{
mType = DerivedType::NONE;
}
virtual ~Base() = default; //You should have a virtual destructor :)
virtual void shared() = 0;
DerivedType GetType() const { return mType; };
protected:
DerivedType mType;
};
// some subclasses with shared and unique methods
class A : public Base
{
public:
A()
{
mType = DerivedType::AType;
}
void shared()
{
cout << "do A stuff\n";
}
void methodUniqueToA()
{
cout << "stuff unique to A\n";
}
};
class B : public Base
{
public:
B()
{
mType = DerivedType::BType;
}
void shared()
{
cout << "do B stuff\n";
}
void methodUniqueToB()
{
cout << "stuff unique to B\n";
}
};
// main
int main()
{
shared_ptr<Base> basePtr;
basePtr = make_shared<B>();
basePtr->shared();
// Here :)
if(basePtr->GetType() == DerivedType::AType)
static_cast<A*>(basePtr.get())->methodUniqueToA();
else if(basePtr->GetType() == DerivedType::BType)
static_cast<B*>(basePtr.get())->methodUniqueToB();
return 0;
}
You can store an enum and initialize it at the constructor. Then have a Getter for that, which will give you the Type. Then a simple static cast after getting the type would do your job!
The goal of using polymorphism for the client is to control different objects with a single way. In other words, the client do not have to pay any attention to the difference of each object. That way, checking the type of each object violates the basic goal.
To achieve the goal, you will have to :
write the concrete method(methodUniqueToX()).
write a wrapper of the concrete method.
name the wrapper method abstract.
make the method public and interface/abstract.
class Base
{
public:
virtual void shared()=0;
virtual void onEvent1()=0;
virtual void onEvent2()=0;
};
// some subclasses with shared and unique methods
class A : public Base
{
private:
void methodUniqueToA()
{
cout << "stuff unique to A\n";
}
public:
void shared()
{
cout << "do A stuff\n";
}
void onEvent1()
{
this.methodUniqueToA()
}
void onEvent2()
{
}
};
class B : public Base
{
private:
void methodUniqueToB()
{
cout << "stuff unique to B\n";
}
public:
void shared()
{
cout << "do B stuff\n";
}
void onEvent1()
{
}
void onEvent2()
{
methodUniqueToB()
}
};

Injecting a function into a subclass

Is it possible to do such things in C++14. I have a base class as follows:
#include <iostream>
class AbstractElement;
class ConcreteElement;
class SuperConcreteElement;
class B
{
public:
void bar(AbstractElement*)
{
std::cout << "Abstract element" << std::endl;
}
void bar(ConcreteElement*)
{
std::cout << "Concrete element" << std::endl;
}
void bar(SuperConcreteElement*)
{
std::cout << "Super concrete element" << std::endl;
}
};
class AbstractElement
{
public:
virtual void foo() = 0;
};
class ConcreteElement : public AbstractElement
{
private:
B _b;
public:
void foo()
{
_b.bar(this); //1
}
};
class SuperConcreteElement : public AbstractElement
{
private:
B _b;
public:
void foo()
{
_b.bar(this); //2
}
};
int main()
{
AbstractElement *e = new ConcreteElement();
e -> foo(); //Prints Concrete element
}
As you can see at //1 and //2, the function's body is completely similar. But I can't quite move it into a base class because of depending on the static type of this. In spite of that fact, I wouldn't like to write absolutely the same code every time I need to add one more subclass of AbstractElement. So, I need some kind of mechanism which provides us with the facility to inject code into a function.
As long as marcos are not very desirable solution, I'd like to ask about some tricks that can be done in C++14 for solving such a problem.
Yes, it is possible using CRTP:
#include <iostream>
class AbstractElement;
class ConcreteElement;
class SuperConcreteElement;
class B
{
public:
void bar(AbstractElement*)
{
std::cout << "Abstract element" << std::endl;
}
void bar(ConcreteElement*)
{
std::cout << "Concrete element" << std::endl;
}
void bar(SuperConcreteElement*)
{
std::cout << "Super concrete element" << std::endl;
}
};
class AbstractElement
{
public:
virtual void foo() = 0;
};
template <class T>
class CRTPAbstractElement : public AbstractElement
{
B _b;
public:
virtual void foo()
{
T* t = dynamic_cast<T *>(this);
_b.bar(t);
}
};
class ConcreteElement : public CRTPAbstractElement<ConcreteElement>
{
};
class SuperConcreteElement : public CRTPAbstractElement<SuperConcreteElement>
{
};
int main()
{
AbstractElement *e = new ConcreteElement();
e -> foo(); //Prints Concrete element
}
By adding an intermediate CRTP class we are able to cast a pointer to the base class to a pointer to the derived class. Thus solving the issue of code duplication.

C++ Override Pure Virtual Function with Function Pointer

If I have a pure virtual function can it be overriden with a function pointer? Scenario below (I'm aware that it's not 100% syntactically correct):
#include<iostream>
using namespace std;
class A {
public:
virtual void foo() = 0;
};
class B : public A {
public:
B() { foo = &B::caseOne; }
void caseOne() { cout << "Hello One" << endl; }
void caseTwo() { cout << "Hello Two" << endl; }
void (B::*foo)();
void chooseOne() { foo = &B::caseOne; }
void chooseTwo() { foo = &B::caseTwo; }
};
int main() {
B b;
b.(*foo)();
}
EDIT: In case anyone's interested, here's how I accomplished what I wanted to do:
#include<iostream>
using namespace std;
class A {
public:
virtual void foo() = 0;
};
class B : public A {
public:
B() { f = &B::caseOne; }
void caseOne() { cout << "Hello One" << endl; }
void caseTwo() { cout << "Hello Two" << endl; }
void (B::*f)();
void chooseOne() { f = &B::caseOne; }
void chooseTwo() { f = &B::caseTwo; }
void foo() { (this->*f)(); }
};
int main() {
B b;
b.foo();
b.chooseTwo();
b.foo();
}
The output is:
Hello One
Hello Two
No. And you use this wrong. In your code you are trying to assign member-function pointer to function-pointer - it's cannot be compiled.
C++03 standard 10.3/2
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or
indirectly from Base, a member function vf with the same name and same parameter list as Base::vf is
declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides
Base::vf.
As #ForEveR said, your code cannot compile. However, since what you actually need is the ability of switching B's implementation of foo in the runtime, we do have workaround:
#include <iostream>
using namespace std;
class A {
public:
virtual void foo() = 0;
};
class B : public A {
private:
void (B::*_f)();
public:
B() { chooseOne(); }
void caseOne() {
cout << "case one" << endl;
}
void caseTwo() {
cout << "case two" << endl;
}
void chooseOne() { _f = &B::caseOne; }
void chooseTwo() { _f = &B::caseTwo; }
void foo() {
(this->*_f)();
}
};
int main(int argc, const char *argv[])
{
A* b = new B();
b->foo();
((B*)b)->chooseTwo();
b->foo();
return 0;
}
UPDATE:
Just found the OP added his answer in the question, which is almost the same as mine. But I think calling foo through pointer instead of instance object is better, for that can exhibit the effect of polymorphism. Besides, it's better to hide f as a private member function.
I think when compile time, the syntax can NOT be compiled. You should provide an override function with the certain name and same args list.

Is there any automated way to implement post-constructor and pre-destructor virtual method calls?

Due to the well-known issues with calling virtual methods from inside constructors and destructors, I commonly end up with classes that need a final-setup method to be called just after their constructor, and a pre-teardown method to be called just before their destructor, like this:
MyObject * obj = new MyObject;
obj->Initialize(); // virtual method call, required after ctor for (obj) to run properly
[...]
obj->AboutToDelete(); // virtual method call, required before dtor for (obj) to clean up properly
delete obj;
This works, but it carries with it the risk that the caller will forget to call either or both of those methods at the appropriate times.
So the question is: Is there any way in C++ to get those methods to be called automatically, so the caller doesn't have to remember to do call them? (I'm guessing there isn't, but I thought I'd ask anyway just in case there is some clever way to do it)
While there is no automated way, you could force the users hand by denying users access to the destructor on that type and declaring a special delete method. In this method you could do the virtual calls you'd like. Creation can take a similar approach which a static factory method.
class MyObject {
...
public:
static MyObject* Create() {
MyObject* pObject = new MyObject();
pObject->Initialize();
return pObject;
}
Delete() {
this->AboutToDelete();
delete this;
}
private:
MyObject() { ... }
virtual ~MyObject() { ... }
};
Now it is not possible to call "delete obj;" unless the call site has access to MyObject private members.
The best I can think of is for you to implement your own smart pointer with a static Create method that news up an instance and calls Initialize, and in its destructor calls AboutToDelete and then delete.
I used a very carefully designed Create() factory method (static member of each class) to call a constructor and initializer pair in the same order as C# initializes types. It returned a shared_ptr to an instance of the type, guaranteeing a heap allocation. It proved reliable and consistent over time.
The trick: I generated my C++ class declarations from XML...
Except for JavedPar's idea for the pre-destruction method, there is no pre-made solution to easily do two-phase construction/destruction in C++. The most obvious way to do this is to follow the Most Common Answer To Problems In C++: "Add another layer of indirection."
You can wrap objects of this class hierarchy within another object. That object's constructors/destructor could then call these methods. Look into Couplien's letter-envelop idiom, for example, or use the smart pointer approach already suggested.
http://www.research.att.com/~bs/wrapper.pdf This paper from Stroustrup will solve your problem.
I tested this under VS 2008 and on UBUNTU against g++ compiler. It worked fine.
#include <iostream>
using namespace std;
template<class T>
class Wrap
{
typedef int (T::*Method)();
T* p;
Method _m;
public:
Wrap(T*pp, Method m): p(pp), _m(m) { (p->*_m)(); }
~Wrap() { delete p; }
};
class X
{
public:
typedef int (*Method)();
virtual int suffix()
{
cout << "X::suffix\n";
return 1;
}
virtual void prefix()
{
cout << "X::prefix\n";
}
X() { cout << "X created\n"; }
virtual ~X() { prefix(); cout << "X destroyed\n"; }
};
class Y : public X
{
public:
Y() : X() { cout << "Y created\n"; }
~Y() { prefix(); cout << "Y destroyed\n"; }
void prefix()
{
cout << "Y::prefix\n";
}
int suffix()
{
cout << "Y::suffix\n";
return 1;
}
};
int main()
{
Wrap<X> xx(new X, &X::suffix);
Wrap<X>yy(new Y, &X::suffix);
}
I was stuck with the same problem, and after a bit of research, I believe there is not any standard solution.
The suggestions that I liked most are the ones provided in the Aleksandrescu et al. book "C++ coding standards" in the item 49.
Quoting them (fair use), you have several options:
Just document it that you need a second method, as you did.
Have another internal state (a boolean) that flags if post-construction has taken place
Use virtual class semantics, in the sense that the constructor of the most-derived class decides which base class to use
Use a factory function.
See his book for details.
You can use static function template in the class. With private ctor/dtor.
Run on vs2015 community
class A {
protected:
A() {}
virtual ~A() {}
virtual void onNew() = 0;
virtual void onDelete() = 0;
public:
void destroy() {
onDelete();
delete this;
}
template <class T> static T* create() {
static_assert(std::is_base_of<A, T>::value, "T must be a descendant of A");
T* t = new T();
t->onNew();
return t;
}
};
class B: public A {
friend A;
protected:
B() {}
virtual ~B() {}
virtual void onNew() override {
}
virtual void onDelete() override {
}
};
int main() {
B* b;
b = A::create<B>();
b->destroy();
}
The main problem with adding post-constructors to C++ is that nobody has yet established how to deal with post-post-constructors, post-post-post-constructors, etc.
The underlying theory is that objects have invariants. This invariant is established by the constructor. Once it has been established, methods of that class can be called. With the introduction of designs that would require post-constructors, you are introducing situations in which class invariants do not become established once the constructor has run. Therefore, it would be equally unsafe to allow calls to virtual functions from post-constructors, and you immediately lose the one apparent benefit they seemed to have.
As your example shows (probably without you realizing), they're not needed:
MyObject * obj = new MyObject;
obj->Initialize(); // virtual method call, required after ctor for (obj) to run properly
obj->AboutToDelete(); // virtual method call, required before dtor for (obj) to clean up properly
delete obj;
Let's show why these methods are not needed. These two calls can invoke virtual functions from MyObject or one of its bases. However, MyObject::MyObject() can safely call those functions too. There is nothing that happens after MyObject::MyObject() returns which would make obj->Initialize() safe. So either obj->Initialize() is wrong or its call can be moved to MyObject::MyObject(). The same logic applies in reverse to obj->AboutToDelete(). The most derived destructor will run first and it can still call all virtual functions, including AboutToDelete().
I had the same problem for construction. This is my solution using C++14.
The idea is to declare an instance of the class Call in the same (or quite close) scope than the declaration of the final object, letting the destructor call the post-creation script.
# include <iostream>
# include <cassert>
# include <memory>
# include <typeinfo>
class A;
// This non-template class stores an access to the instance
// on which a procedure must be called after construction
// The functions are defined after A in order to avoid a loop
class Call
{
protected:
A* a;
public:
Call();
virtual ~Call();
virtual void set(A& a_) = 0;
};
// In this class, the Source must be the final type created
template <typename Source>
class Call_ : public Call
{
static_assert(std::is_final<Source>::value, "");
public:
Call_() : Call() {}
virtual ~Call_() { assert(typeid(*this->a) == typeid(Source)); }
virtual void set(A& a_) { this->a = &a_; }
};
class A
{
protected:
A(Call& call) { std::cout << "Build A" << std::endl; call.set(*this); } // <----
public:
A(A const&) { std::cout << "Copy A" << std::endl; }
virtual ~A() { std::cout << "Delete A" << std::endl; }
virtual void actions_after_construction() = 0; // post-creation procedure
};
Call::Call() : a(nullptr)
{}
Call::~Call()
{
assert(this->a);
this->a->actions_after_construction();
}
class B : public A
{
protected:
B(Call& call) : A(call) { std::cout << "Build B" << std::endl; }
public:
B(B const& b) : A(b) { std::cout << "Copy B" << std::endl; }
virtual ~B() { std::cout << "Delete B" << std::endl; }
virtual void actions_after_construction() { std::cout << "actions by B" << std::endl; }
};
class C final : public B
{
private:
C(Call& call) : B(call) { std::cout << "Build C" << std::endl; }
public:
C(std::shared_ptr<Call> p_call = std::shared_ptr<Call>(new Call_<C>)) : C(*p_call) {}
C(C const& c) : B(c) { std::cout << "Copy C" << std::endl; }
virtual ~C() { std::cout << "Delete C" << std::endl; }
virtual void actions_after_construction() { std::cout << "actions by C" << std::endl; }
};
class D final : public B
{
private:
D(Call& call) : B(call) { std::cout << "Build D" << std::endl; }
public:
D(std::shared_ptr<Call> p_call = std::shared_ptr<Call>(new Call_<D>)) : D(*p_call) {}
D(D const& d) : B(d) { std::cout << "Copy D" << std::endl; }
virtual ~D() { std::cout << "Delete D" << std::endl; }
virtual void actions_after_construction() { std::cout << "actions by D" << std::endl; }
};
int main()
{
{ C c; }
{ D d; }
return 0;
}
Haven't seen the answer yet, but base classes are only one way to add code in a class hierarchy. You can also create classes designed to be added to the other side of the hierarchy:
template<typename Base>
class Derived : public Base {
// You'd need C++0x to solve the forwarding problem correctly.
Derived() : Base() {
Initialize();
}
template<typename T>
Derived(T const& t): Base(t) {
Initialize();
}
//etc
private:
Initialize();
};

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

I was thinking along the lines of using typeid() but I don't know how to ask if that type is a subclass of another class (which, by the way, is abstract)
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;
}
}
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".
You can do it with dynamic_cast (at least for polymorphic types).
Actually, on second thought--you can't tell if it is SPECIFICALLY a particular type with dynamic_cast--but you can tell if it is that type or any subclass thereof.
template <class DstType, class SrcType>
bool IsType(const SrcType* src)
{
return dynamic_cast<const DstType*>(src) != nullptr;
}
The code below demonstrates 3 different ways of doing it:
virtual function
typeid
dynamic_cast
#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;
}
The program above prints this:
type A
type A
type A
dynamic_cast can determine if the type contains the target type anywhere in the inheritance hierarchy (yes, it's a little-known feature that if B inherits from A and C, it can turn an A* directly into a C*). typeid() can determine the exact type of the object. However, these should both be used extremely sparingly. As has been mentioned already, you should always be avoiding dynamic type identification, because it indicates a design flaw. (also, if you know the object is for sure of the target type, you can do a downcast with a static_cast. Boost offers a polymorphic_downcast that will do a downcast with dynamic_cast and assert in debug mode, and in release mode it will just use a 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)
{
...
}
According to documentation, SuperSubClass<B,D>::value will be true if B is a public base of D, or if B and D are aliases of the same type.
i.e. either D is a subclass of B or D is the same as B.
I hope this helps.
edit:
Please note the evaluation of SuperSubClass<B,D>::value happens at compile time unlike some methods which use dynamic_cast, hence there is no penalty for using this system at runtime.
I disagree that you should never want to check an object's type in C++. If you can avoid it, I agree that you should. Saying you should NEVER do this under any circumstance is going too far though. You can do this in a great many languages, and it can make your life a lot easier. Howard Pinsley, for instance, showed us how in his post on C#.
I do a lot of work with the Qt Framework. In general, I model what I do after the way they do things (at least when working in their framework). The QObject class is the base class of all Qt objects. That class has the functions isWidgetType() and isWindowType() as a quick subclass check. So why not be able to check your own derived classes, which is comparable in it's nature? Here is a QObject spin off of some of these other posts:
class MyQObject : public QObject
{
public:
MyQObject( QObject *parent = 0 ) : QObject( parent ){}
~MyQObject(){}
static bool isThisType( const QObject *qObj )
{ return ( dynamic_cast<const MyQObject*>(qObj) != NULL ); }
};
And then when you are passing around a pointer to a QObject, you can check if it points to your derived class by calling the static member function:
if( MyQObject::isThisType( qObjPtr ) ) qDebug() << "This is a MyQObject!";
#include <stdio.h>
#include <iostream.h>
class Base
{
public: virtual ~Base() {}
template<typename T>
bool isA() {
return (dynamic_cast<T*>(this) != NULL);
}
};
class D1: public Base {};
class D2: public Base {};
class D22: public D2 {};
int main(int argc,char* argv[]);
{
D1* d1 = new D1();
D2* d2 = new D2();
D22* d22 = new D22();
Base* x = d22;
if( x->isA<D22>() )
{
std::cout << "IS A D22" << std::endl;
}
if( x->isA<D2>() )
{
std::cout << "IS A D2" << std::endl;
}
if( x->isA<D1>() )
{
std::cout << "IS A D1" << std::endl;
}
if(x->isA<Base>() )
{
std::cout << "IS A Base" << std::endl;
}
}
Result:
IS A D22
IS A D2
IS A Base
I was thinking along the lines of using typeid()...
Well, yes, it could be done by comparing: typeid().name(). If we take the already described situation, where:
class Base;
class A : public Base {...};
class B : public Base {...};
void foo(Base *p)
{
if(/* p is A */) /* do X */
else /* do Y */
}
A possible implementation of foo(Base *p) would be:
#include <typeinfo>
void foo(Base *p)
{
if(typeid(*p) == typeid(A))
{
// the pointer is pointing to the derived class A
}
else if (typeid(*p).name() == typeid(B).name())
{
// the pointer is pointing to the derived class B
}
}
I see some good answers here and I see some dumb response.
"Trying to query the type of an object is a design flaw". Which means that Java instanceof and C# is keywords are design flaws. These are response of people that dont rate polymorphism. If you have an interface, that interface is derived by another interface that impelments more features. If you need these extra features you must first check that you have such an interface. Even microsoft COM API makes use of this design.
Then in terms of how to deduce if an object is a instanceof a class, many good answers have already been given
typeid
having a virtual type function
dynamic cast
is_base_of has nothing to do with polymorphism.
And having each virtual function define its own type method is unnecessary as it is redundant. Each virtual class already has a pointer to its virtual table.
class Base
{
void *p_virtual_table = BASE_VIRTUAL_TABLE;
}
class Derived : Base
{
void *p_virtual_table = DERIVED_VIRTUAL_TABLE;
}
void *BASE_VIRTUAL_TABLE[n];
void *DERIVED_VIRTUAL_TABLE[n];
The point here is that the address of the virtual tables are fixed and a simple comparrison will decide if a virtual object is an instanceof a virtual class.
Since cpp doesnt give us a standard way of accessing the virtual tables, it would be hard to do these comparrisons manually. But the cpp abstract machine has absolutely no problems deducing the exact instance of a virtual object.
You can only do it at compile time using templates, unless you use RTTI.
It lets you use the typeid function which will yield a pointer to a type_info structure which contains information about the type.
Read up on it at Wikipedia
You can do it with templates (or SFINAE (Substitution Failure Is Not An Error)). Example:
#include <iostream>
class base
{
public:
virtual ~base() = default;
};
template <
class type,
class = decltype(
static_cast<base*>(static_cast<type*>(0))
)
>
bool check(type)
{
return true;
}
bool check(...)
{
return false;
}
class child : public base
{
public:
virtual ~child() = default;
};
class grandchild : public child {};
int main()
{
std::cout << std::boolalpha;
std::cout << "base: " << check(base()) << '\n';
std::cout << "child: " << check(child()) << '\n';
std::cout << "grandchild: " << check(grandchild()) << '\n';
std::cout << "int: " << check(int()) << '\n';
std::cout << std::flush;
}
Output:
base: true
child: true
grandchild: true
int: false
As a spin off of multiple other answers (including one I previously posted myself!), here's a macro to help:
#define isInstance( ptr, clazz ) (dynamic_cast<const clazz*>(ptr) != NULL)
In c# you can simply say:
if (myObj is Car) {
}