I am quite confused with the dynamic_cast keyword in C++.
struct A {
virtual void f() { }
};
struct B : public A { };
struct C { };
void f () {
A a;
B b;
A* ap = &b;
B* b1 = dynamic_cast<B*> (&a); // NULL, because 'a' is not a 'B'
B* b2 = dynamic_cast<B*> (ap); // 'b'
C* c = dynamic_cast<C*> (ap); // NULL.
A& ar = dynamic_cast<A&> (*ap); // Ok.
B& br = dynamic_cast<B&> (*ap); // Ok.
C& cr = dynamic_cast<C&> (*ap); // std::bad_cast
}
the definition says:
The dynamic_cast keyword casts a datum from one pointer or reference
type to another, performing a runtime check to ensure the validity of the cast
Can we write an equivalent of dynamic_cast of C++ in C so that I could better understand things?
Here's a rundown on static_cast<> and dynamic_cast<> specifically as they pertain to pointers. This is just a 101-level rundown, it does not cover all the intricacies.
static_cast< Type* >(ptr)
This takes the pointer in ptr and tries to safely cast it to a pointer of type Type*. This cast is done at compile time. It will only perform the cast if the types are related. If the types are not related, you will get a compiler error. For example:
class B {};
class D : public B {};
class X {};
int main()
{
D* d = new D;
B* b = static_cast<B*>(d); // this works
X* x = static_cast<X*>(d); // ERROR - Won't compile
return 0;
}
dynamic_cast< Type* >(ptr)
This again tries to take the pointer in ptr and safely cast it to a pointer of type Type*. But this cast is executed at runtime, not compile time. Because this is a run-time cast, it is useful especially when combined with polymorphic classes. In fact, in certain cases the classes must be polymorphic in order for the cast to be legal.
Casts can go in one of two directions: from base to derived (B2D) or from derived to base (D2B). It's simple enough to see how D2B casts would work at runtime. Either ptr was derived from Type or it wasn't. In the case of D2B dynamic_cast<>s, the rules are simple. You can try to cast anything to anything else, and if ptr was in fact derived from Type, you'll get a Type* pointer back from dynamic_cast. Otherwise, you'll get a NULL pointer.
But B2D casts are a little more complicated. Consider the following code:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void DoIt() = 0; // pure virtual
virtual ~Base() {};
};
class Foo : public Base
{
public:
virtual void DoIt() { cout << "Foo"; };
void FooIt() { cout << "Fooing It..."; }
};
class Bar : public Base
{
public :
virtual void DoIt() { cout << "Bar"; }
void BarIt() { cout << "baring It..."; }
};
Base* CreateRandom()
{
if( (rand()%2) == 0 )
return new Foo;
else
return new Bar;
}
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = (Bar*)base;
bar->BarIt();
}
return 0;
}
main() can't tell what kind of object CreateRandom() will return, so the C-style cast Bar* bar = (Bar*)base; is decidedly not type-safe. How could you fix this? One way would be to add a function like bool AreYouABar() const = 0; to the base class and return true from Bar and false from Foo. But there is another way: use dynamic_cast<>:
int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();
base->DoIt();
Bar* bar = dynamic_cast<Bar*>(base);
Foo* foo = dynamic_cast<Foo*>(base);
if( bar )
bar->BarIt();
if( foo )
foo->FooIt();
}
return 0;
}
The casts execute at runtime, and work by querying the object (no need to worry about how for now), asking it if it the type we're looking for. If it is, dynamic_cast<Type*> returns a pointer; otherwise it returns NULL.
In order for this base-to-derived casting to work using dynamic_cast<>, Base, Foo and Bar must be what the Standard calls polymorphic types. In order to be a polymorphic type, your class must have at least one virtual function. If your classes are not polymorphic types, the base-to-derived use of dynamic_cast will not compile. Example:
class Base {};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile
return 0;
}
Adding a virtual function to base, such as a virtual dtor, will make both Base and Der polymorphic types:
class Base
{
public:
virtual ~Base(){};
};
class Der : public Base {};
int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // OK
return 0;
}
Unless you're implementing your own hand-rolled RTTI (and bypassing the system one), it's not possible to implement dynamic_cast directly in C++ user-level code. dynamic_cast is very much tied into the C++ implementation's RTTI system.
But, to help you understand RTTI (and thus dynamic_cast) more, you should read up on the <typeinfo> header, and the typeid operator. This returns the type info corresponding to the object you have at hand, and you can inquire various (limited) things from these type info objects.
More than code in C, I think that an english definition could be enough:
Given a class Base of which there is a derived class Derived, dynamic_cast will convert a Base pointer to a Derived pointer if and only if the actual object pointed at is in fact a Derived object.
class Base { virtual ~Base() {} };
class Derived : public Base {};
class Derived2 : public Base {};
class ReDerived : public Derived {};
void test( Base & base )
{
dynamic_cast<Derived&>(base);
}
int main() {
Base b;
Derived d;
Derived2 d2;
ReDerived rd;
test( b ); // throw: b is not a Derived object
test( d ); // ok
test( d2 ); // throw: d2 is not a Derived object
test( rd ); // ok: rd is a ReDerived, and thus a derived object
}
In the example, the call to test binds different objects to a reference to Base. Internally the reference is downcasted to a reference to Derived in a typesafe way: the downcast will succeed only for those cases where the referenced object is indeed an instance of Derived.
First, to describe dynamic cast in C terms, we have to represent classes in C.
Classes with virtual functions use a "VTABLE" of pointers to the virtual functions.
Comments are C++. Feel free to reformat and fix compile errors...
// class A { public: int data; virtual int GetData(){return data;} };
typedef struct A { void**vtable; int data;} A;
int AGetData(A*this){ return this->data; }
void * Avtable[] = { (void*)AGetData };
A * newA() { A*res = malloc(sizeof(A)); res->vtable = Avtable; return res; }
// class B : public class A { public: int moredata; virtual int GetData(){return data+1;} }
typedef struct B { void**vtable; int data; int moredata; } B;
int BGetData(B*this){ return this->data + 1; }
void * Bvtable[] = { (void*)BGetData };
B * newB() { B*res = malloc(sizeof(B)); res->vtable = Bvtable; return res; }
// int temp = ptr->GetData();
int temp = ((int(*)())ptr->vtable[0])();
Then a dynamic cast is something like:
// A * ptr = new B();
A * ptr = (A*) newB();
// B * aB = dynamic_cast<B>(ptr);
B * aB = ( ptr->vtable == Bvtable ? (B*) aB : (B*) 0 );
The following is not really close to what you get from C++'s dynamic_cast in terms of type checking but maybe it will help you understand its purpose a little bit better:
struct Animal // Would be a base class in C++
{
enum Type { Dog, Cat };
Type type;
};
Animal * make_dog()
{
Animal * dog = new Animal;
dog->type = Animal::Dog;
return dog;
}
Animal * make_cat()
{
Animal * cat = new Animal;
cat->type = Animal::Cat;
return cat;
}
Animal * dyn_cast(AnimalType type, Animal * animal)
{
if(animal->type == type)
return animal;
return 0;
}
void bark(Animal * dog)
{
assert(dog->type == Animal::Dog);
// make "dog" bark
}
int main()
{
Animal * animal;
if(rand() % 2)
animal = make_dog();
else
animal = make_cat();
// At this point we have no idea what kind of animal we have
// so we use dyn_cast to see if it's a dog
if(dyn_cast(Animal::Dog, animal))
{
bark(animal); // we are sure the call is safe
}
delete animal;
}
A dynamic_cast performs a type checking using RTTI. If it fails it'll throw you an exception (if you gave it a reference) or NULL if you gave it a pointer.
There are no classes in C, so it's impossible to to write dynamic_cast in that language. C structures don't have methods (as a result, they don't have virtual methods), so there is nothing "dynamic" in it.
No, not easily. The compiler assigns a unique identity to every class, that information is referenced by every object instance, and that is what gets inspected at runtime to determine if a dynamic cast is legal. You could create a standard base class with this information and operators to do the runtime inspection on that base class, then any derived class would inform the base class of its place in the class hierarchy and any instances of those classes would be runtime-castable via your operations.
edit
Here's an implementation that demonstrates one technique. I'm not claiming the compiler uses anything like this, but I think it demonstrates the concepts:
class SafeCastableBase
{
public:
typedef long TypeID;
static TypeID s_nextTypeID;
static TypeID GetNextTypeID()
{
return s_nextTypeID++;
}
static TypeID GetTypeID()
{
return 0;
}
virtual bool CanCastTo(TypeID id)
{
if (GetTypeID() != id) { return false; }
return true;
}
template <class Target>
static Target *SafeCast(SafeCastableBase *pSource)
{
if (pSource->CanCastTo(Target::GetTypeID()))
{
return (Target*)pSource;
}
return NULL;
}
};
SafeCastableBase::TypeID SafeCastableBase::s_nextTypeID = 1;
class TypeIDInitializer
{
public:
TypeIDInitializer(SafeCastableBase::TypeID *pTypeID)
{
*pTypeID = SafeCastableBase::GetNextTypeID();
}
};
class ChildCastable : public SafeCastableBase
{
public:
static TypeID s_typeID;
static TypeID GetTypeID()
{
return s_typeID;
}
virtual bool CanCastTo(TypeID id)
{
if (GetTypeID() != id) { return SafeCastableBase::CanCastTo(id); }
return true;
}
};
SafeCastableBase::TypeID ChildCastable::s_typeID;
TypeIDInitializer ChildCastableInitializer(&ChildCastable::s_typeID);
class PeerChildCastable : public SafeCastableBase
{
public:
static TypeID s_typeID;
static TypeID GetTypeID()
{
return s_typeID;
}
virtual bool CanCastTo(TypeID id)
{
if (GetTypeID() != id) { return SafeCastableBase::CanCastTo(id); }
return true;
}
};
SafeCastableBase::TypeID PeerChildCastable::s_typeID;
TypeIDInitializer PeerChildCastableInitializer(&PeerChildCastable::s_typeID);
int _tmain(int argc, _TCHAR* argv[])
{
ChildCastable *pChild = new ChildCastable();
SafeCastableBase *pBase = new SafeCastableBase();
PeerChildCastable *pPeerChild = new PeerChildCastable();
ChildCastable *pSameChild = SafeCastableBase::SafeCast<ChildCastable>(pChild);
SafeCastableBase *pBaseToChild = SafeCastableBase::SafeCast<SafeCastableBase>(pChild);
ChildCastable *pNullDownCast = SafeCastableBase::SafeCast<ChildCastable>(pBase);
SafeCastableBase *pBaseToPeerChild = SafeCastableBase::SafeCast<SafeCastableBase>(pPeerChild);
ChildCastable *pNullCrossCast = SafeCastableBase::SafeCast<ChildCastable>(pPeerChild);
return 0;
}
static_cast< Type* >(ptr)
static_cast in C++ can be used in scenarios where all type casting can be verified at compile time.
dynamic_cast< Type* >(ptr)
dynamic_cast in C++ can be used to perform type safe down casting. dynamic_cast is run time polymorphism. The dynamic_cast operator, which safely converts from a pointer (or reference) to a base type to a pointer (or reference) to a derived type.
eg 1:
#include <iostream>
using namespace std;
class A
{
public:
virtual void f(){cout << "A::f()" << endl;}
};
class B : public A
{
public:
void f(){cout << "B::f()" << endl;}
};
int main()
{
A a;
B b;
a.f(); // A::f()
b.f(); // B::f()
A *pA = &a;
B *pB = &b;
pA->f(); // A::f()
pB->f(); // B::f()
pA = &b;
// pB = &a; // not allowed
pB = dynamic_cast<B*>(&a); // allowed but it returns NULL
return 0;
}
For more information click here
eg 2:
#include <iostream>
using namespace std;
class A {
public:
virtual void print()const {cout << " A\n";}
};
class B {
public:
virtual void print()const {cout << " B\n";}
};
class C: public A, public B {
public:
void print()const {cout << " C\n";}
};
int main()
{
A* a = new A;
B* b = new B;
C* c = new C;
a -> print(); b -> print(); c -> print();
b = dynamic_cast< B*>(a); //fails
if (b)
b -> print();
else
cout << "no B\n";
a = c;
a -> print(); //C prints
b = dynamic_cast< B*>(a); //succeeds
if (b)
b -> print();
else
cout << "no B\n";
}
dynamic_cast uses RTTI. It can slow down your application, you can use modification of the visitor design pattern to achieve downcasting without RTTI http://arturx64.github.io/programming-world/2016/02/06/lazy-visitor.html
Related
I have the following structure of classes:
struct A {
virtual void function() = 0;
};
struct B : A {
void function() override {
// ...implementation...
}
};
struct C {
virtual A a() = 0;
};
struct D : public C {
A a() {
return B{};
}
}
the main idea is: I do not really care what class will be returned from D::a, the only property I want it to have is a function() member-function. So I denoted the return type as the abstract class A which has this property as virtual, and then try to return B object which is derived from A. But this does not work, giving error: invalid abstract return type. Could you please suggest a way to achieve the desired effect in C++?
In C++, you can't do polymorphism with objects, because objects could have different sizes, and in C++ types have value semantics. You can, however, do polymorphism with references, and pointers. So your function could be:
A* a();
// or
A& a();
This does mean that you may have problems with ownership. You can also return a smart pointer instead:
unique_ptr<A> a();
You can't create objects of abstract types, you can create pointers of them. As Ayxan said, you can use also smart pointers, but I suggest you use shared_ptr because it's more comfortable.
Use dynamic_cast to convert B to A.
You forgot to add ; to the end of the third struct.
Here is the correct code:
#include <iostream>
struct A {
virtual void function() = 0;
};
struct B : A {
void function() override {
std::cout << "EEAAAHHHH\n";
}
};
struct C {
virtual A* a() = 0;
};
struct D : public C {
A* a() {
B *a = new B;
A *b = dynamic_cast<A*>(a);
return b;
}
};
int main()
{
D d;
A* a = d.a();
a->function();
return 0;
}
If you compile and run the code, you can see that the output is "EEAAAHHHH".
I'm happy to help you, and I wish you success.
This question already has answers here:
"Overloading" pure virtual function with different set of arguments
(5 answers)
Closed 2 years ago.
I am trying to understand inheritance and polymorphism. When I run this :
#include<iostream>
using namespace std;
class Base
{
int x;
public:
virtual Base* fun() = 0;
int getX() { return x; }
};
// This class inherits from Base and implements fun()
class Derived: public Base
{
public:
int y;
Derived* fun() {
Derived *d = new Derived;
d->y = 2;
return d;
}
};
int main(void)
{
Derived d;
Derived *p = d.fun();
cout<< p->y;
}
This works fine as it is legal for a derived class to override a virtual function using a different return type as long as the return type is covariant with the original return type
But what if the virtual function contain the input argument of type Base*. Like :
#include<iostream>
using namespace std;
class Base
{
int x;
public:
virtual Base* fun(Base * t) = 0;
int getX() { return x; }
};
// This class inherits from Base and implements fun()
class Derived: public Base
{
public:
int y;
Derived* fun(Derived *t) {
Derived *d = new Derived;
d->y = t->y;
return d;
}
};
int main(void)
{
Derived d;
Derived *p = d.fun();
cout<< p->y;
}
This is throwing error error: invalid new-expression of abstract class type ‘Derived’ Derived *d = new Derived; which I understand it means that compiler is not recognising the implementation of the virtual function and considering the class ``Derived``` as abstract.
So how can we override virtual function of this type ??
I tried to search it , but didn't find any reference. If similar question exists , let me know.
Thanks
If I needed this in my own code. I'd write the new derived class like this:
// This class inherits from Base and implements fun()
class Derived: public Base
{
public:
int y;
Derived* fun(Base *t) {
Derived *d = new Derived;
Derived* input = dynamic_cast<Derived *>(t);
ASSERT(input); // Cause the debug version to throw an exception so the error can be debugged
if(input)
d->y = t->y;
else
d->y = 0; // Or the default of your choice.
return d;
}
};
This introduces a potential runtime error if the base type passed in is not the correct derived type. But I don't see a way to avoid it.
The other options I see are use templates. Where the derived type requires the derived type to be passed in. Or simply create a new function that takes the derived type as input and also overrides fun(Base *t);
using namespace std;
template <class T>
class Base
{
int x;
public:
virtual T* fun(T* t) = 0;
int getX() { return x; }
};
class Derived : public Base<Derived>
{
public:
int y;
Derived() { y = 0; }
Derived* fun(Derived* t) {
Derived *d = new Derived;
d->y = t->y;
return d;
}
};
int main(int argc, const char* argv[])
{
Derived *d = new Derived;
Derived * p = d->fun(d);
cout << p->y;
return 0;
}
test in visual studio 2019.
Suppose there is a class A which has two subclasses, Aa and Ab. I want to make an array that can store pointers to objects of class Aa and Ab. If an array is declared with the type of class A, is this valid? If not, how can I accomplish this? For example:
A *arr;
//space allocated
Ab *obj1;
arr[x] = obj1;
On a related note, I want to write a function that when given a location, will return the object stored at that location in the array. If the above works and I have an array of objects of either Aa or Ab, the function could return an object of either type Aa or Ab. If the return type of the function is specified as A, the superclass, is this valid? If not, I have looked at template functions but cannot find a straight answer about just having the return type be variable, not the parameters. For this example, the function's parameter is always going to be int, but it could return an Aa or an Ab, depending on what is at that location in the array.
Yes that is the way polymorohism is achieved (using pointer to base class) and virtual methods.
Here is an example:
#include <iostream>
using namespace std;
#include <vector>
class A{
public:
virtual void foo()const{
std::cout << "A::foo()" << std::endl;
}
};
class Aa : public A {
public:
virtual void foo()const{
std::cout << "Aa::foo()" << std::endl;
}
};
class Ab : public A {
public:
virtual void foo()const{
std::cout << "Ab::foo()" << std::endl;
}
};
int main(){
A* ptrA[3];
A* a = new A;
Aa* aa = new Aa;
Ab* ab = new Ab;
ptrA[0] = aa;
ptrA[1] = ab;
ptrA[2] = a;
for(int i(0); i != 3; ++i)
ptrA[i]->foo();
delete a;
delete aa;
delete ab;
return 0;
}
Remember that C++ is Invariant not Contravariant which means you cannot assign a derived object a base object:
A* a = new A;
Ab* ab = a; // error
Is valid to have an array of base pointers, also you can use dynamic_cast to know in run time the return type of your array and use the API from the derived class. See and example below.
struct Base { virtual void do_something() {} };
struct Derived1 : Base
{
void first() const { std::cout << "first" << std::endl; }
void do_something() override {}
};
struct Derived2 : Base
{
void second() const { std::cout << "second" << std::endl; }
void do_something() override {}
};
Base& get(int option)
{
static std::vector<Base*> b {new Derived1{}, new Derived2{}};
return !option ? *b[0] : *b[1];
}
int main()
{
const int option {0};
// const int option {1};
if (Derived1* derived {dynamic_cast<Derived1*>(&get(option))})
{
derived->first();
}
else if (Derived2* derived {dynamic_cast<Derived2*>(&get(option))})
{
derived->second();
}
}
I'm reading Scott Meyers' More Effective C++ now. Edifying! Item 2 mentions that dynamic_cast can be used not only for downcasts but also for sibling casts. Could please anyone provide a (reasonably) non-contrived example of its usage for siblings? This silly test prints 0 as it should, but I can't imagine any application for such conversions.
#include <iostream>
using namespace std;
class B {
public:
virtual ~B() {}
};
class D1 : public B {};
class D2 : public B {};
int main() {
B* pb = new D1;
D2* pd2 = dynamic_cast<D2*>(pb);
cout << pd2 << endl;
}
The scenario you suggested doesn't match sidecast exactly, which is usually used for the casting between pointers/references of two classes, and the pointers/references are referring to an object of class which both derives from the two classes. Here's an example for it:
struct Readable {
virtual void read() = 0;
};
struct Writable {
virtual void write() = 0;
};
struct MyClass : Readable, Writable {
void read() { std::cout << "read"; }
void write() { std::cout << "write"; }
};
int main()
{
MyClass m;
Readable* pr = &m;
// sidecast to Writable* through Readable*, which points to an object of MyClass in fact
Writable* pw = dynamic_cast<Writable*>(pr);
if (pw) {
pw->write(); // safe to call
}
}
LIVE
It is called cross-cast, and it is used when a class inherits from two different classes (not the other way around, as shown in your question).
For example, given the following class-hierarchy:
A B
\ /
C
If you have an A pointer to a C object, then you can get a B pointer to that C object:
A* ap = new C;
B* bp = dynamic_cast<B*>(ap);
In C++, is there any way to query the type of an object and then use that information to dynamically create a new object of the same type?
For example, say I have a simple 3 class hierarchy:
class Base
class Foo : public Base
class Bar : public Base
Now suppose I give you an object cast as type Base -- which is in reality of type Foo.
Is there a way to query the type and use that info to later create new objects of type Foo?
Clone method
There is nothing provided by the language that queries type and lets you construct from that information, but you can provide the capability for your class hierarchy in various ways, the easiest of which is to use a virtual method:
struct Base {
virtual ~Base();
virtual std::auto_ptr<Base> clone(/*desired parameters, if any*/) const = 0;
};
This does something slightly different: clone the current object. This is often what you want, and allows you to keep objects around as templates, which you then clone and modify as desired.
Expanding on Tronic, you can even generate the clone function.
Why auto_ptr? So you can use new to allocate the object, make the transfer of ownership explicit, and the caller has no doubt that delete must deallocate it. For example:
Base& obj = *ptr_to_some_derived;
{ // since you can get a raw pointer, you have not committed to anything
// except that you might have to type ".release()"
Base* must_free_me = obj.clone().release();
delete must_free_me;
}
{ // smart pointer types can automatically work with auto_ptr
// (of course not all do, you can still use release() for them)
boost::shared_ptr<Base> p1 (obj.clone());
auto_ptr<Base> p2 (obj.clone());
other_smart_ptr<Base> p3 (obj.clone().release());
}
{ // automatically clean up temporary clones
// not needed often, but impossible without returning a smart pointer
obj.clone()->do_something();
}
Object factory
If you'd prefer to do exactly as you asked and get a factory that can be used independently of instances:
struct Factory {}; // give this type an ability to make your objects
struct Base {
virtual ~Base();
virtual Factory get_factory() const = 0; // implement in each derived class
// to return a factory that can make the derived class
// you may want to use a return type of std::auto_ptr<Factory> too, and
// then use Factory as a base class
};
Much of the same logic and functionality can be used as for a clone method, as get_factory fulfills half of the same role, and the return type (and its meaning) is the only difference.
I've also covered factories a couple times already. You could adapt my SimpleFactory class so your factory object (returned by get_factory) held a reference to a global factory plus the parameters to pass to create (e.g. the class's registered name—consider how to apply boost::function and boost::bind to make this easy to use).
The commonly used way to create copies of objects by base class is adding a clone method, which is essentially a polymorphic copy constructor. This virtual function normally needs to be defined in every derived class, but you can avoid some copy&paste by using the Curiously Recurring Template Pattern:
// Base class has a pure virtual function for cloning
class Shape {
public:
virtual ~Shape() {} // Polymorphic destructor to allow deletion via Shape*
virtual Shape* clone() const = 0; // Polymorphic copy constructor
};
// This CRTP class implements clone() for Derived
template <typename Derived> class Shape_CRTP: public Shape {
public:
Shape* clone() const {
return new Derived(dynamic_cast<Derived const&>(*this));
}
};
// Every derived class inherits from Shape_CRTP instead of Shape
// Note: clone() needs not to be defined in each
class Square: public Shape_CRTP<Square> {};
class Circle: public Shape_CRTP<Circle> {};
// Now you can clone shapes:
int main() {
Shape* s = new Square();
Shape* s2 = s->clone();
delete s2;
delete s;
}
Notice that you can use the same CRTP class for any functionality that would be the same in every derived class but that requires knowledge of the derived type. There are many other uses for this besides clone(), e.g. double dispatch.
There's only some hacky ways to do this.
The first and IMHO the ugliest is:
Base * newObjectOfSameType( Base * b )
{
if( dynamic_cast<Foo*>( b ) ) return new Foo;
if( dynamic_cast<Bar*>( b ) ) return new Bar;
}
Note that this will only work if you have RTTI enabled and Base contains some virtual function.
The second an neater version is to add a pure virtual clone function to the base class
struct Base { virtual Base* clone() const=0; }
struct Foo : public Base { Foo* clone() const { return new Foo(*this); }
struct Bar : public Base { Bar* clone() const { return new Bar(*this); }
Base * newObjectOfSameType( Base * b )
{
return b->clone();
}
This is much neater.
One cool/interesting thing about this is that
Foo::clone returns a Foo*, while Bar::clone returns a Bar*. You might expect this to break things, but everything works due to a feature of C++ called covariant return types.
Unfortunately covariant return types don't work for smart pointers, so using sharted_ptrs your code would look like this.
struct Base { virtual shared_ptr<Base> clone() const=0; }
struct Foo : public Base { shared_ptr<Base> clone() const { return shared_ptr<Base>(new Foo(*this) ); }
struct Bar : public Base { shared_ptr<Base> clone() const { return shared_ptr<Base>(new Bar(*this)); }
shared_ptr<Base> newObjectOfSameType( shared_ptr<Base> b )
{
return b->clone();
}
You can use e.g. typeid to query an object's dynamic type, but I don't know of a way to directly instantiate a new object from the type information.
However, apart from the clone approach mentioned above, you could use a factory:
#include <typeinfo>
#include <iostream>
class Base
{
public:
virtual void foo() const
{
std::cout << "Base object instantiated." << std::endl;
}
};
class Derived : public Base
{
public:
virtual void foo() const
{
std::cout << "Derived object instantiated." << std::endl;
}
};
class Factory
{
public:
static Base* createFrom( const Base* x )
{
if ( typeid(*x) == typeid(Base) )
{
return new Base;
}
else if ( typeid(*x) == typeid(Derived) )
{
return new Derived;
}
else
{
return 0;
}
}
};
int main( int argc, char* argv[] )
{
Base* X = new Derived;
if ( X != 0 )
{
std::cout << "X says: " << std::endl;
X->foo();
}
Base* Y = Factory::createFrom( X );
if ( Y != 0 )
{
std::cout << "Y says: " << std::endl;
Y->foo();
}
return 0;
}
P.S.: The essential part of this code example is of course the Factory::createFrom method. (It's probably not the most beautiful C++ code, since my C++ has gone a little rusty. The factory method probably shouldn't be static, on second thought.)
I used macros in my project to synthesize such methods.
I'm just researching this approach now, so I may be wrong, but here's an answer to your question in my code of IAllocable.hh. Note that I use GCC 4.8, but I hope 4.7 suits.
#define SYNTHESIZE_I_ALLOCABLE \
public: \
auto alloc() -> __typeof__(this) { return new (__typeof__(*this))(); } \
IAllocable * __IAllocable_alloc() { return new (__typeof__(*this))(); } \
private:
class IAllocable {
public:
IAllocable * alloc() {
return __IAllocable_alloc();
}
protected:
virtual IAllocable * __IAllocable_alloc() = 0;
};
Usage:
class Usage : public virtual IAllocable {
SYNTHESIZE_I_ALLOCABLE
public:
void print() {
printf("Hello, world!\n");
}
};
int main() {
{
Usage *a = new Usage;
Usage *b = a->alloc();
b->print();
delete a;
delete b;
}
{
IAllocable *a = new Usage;
Usage *b = dynamic_cast<Usage *>(a->alloc());
b->print();
delete a;
delete b;
}
}
Hope it helps.
In C++, is there any way to query the type of an object...
Yes, use typeid() operator
For example:
// typeid, polymorphic class
#include <iostream>
#include <typeinfo>
#include <exception>
using namespace std;
class CBase { virtual void f(){} };
class CDerived : public CBase {};
int main () {
try {
CBase* a = new CBase;
CBase* b = new CDerived;
cout << "a is: " << typeid(a).name() << '\n';
cout << "b is: " << typeid(b).name() << '\n';
cout << "*a is: " << typeid(*a).name() << '\n';
cout << "*b is: " << typeid(*b).name() << '\n';
} catch (exception& e) { cout << "Exception: " << e.what() << endl; }
return 0;
}
Output:
a is: class CBase *
b is: class CBase *
*a is: class CBase
*b is: class CDerived
If the type typeid evaluates is a pointer preceded by the dereference operator (*), and this pointer has a null value, typeid throws a bad_typeid exception
Read more.....
class Base
{
public:
virtual ~Base() { }
};
class Foo : public Base
{
};
class Bar : public Base
{
};
template<typename T1, typename T2>
T1* fun(T1* obj)
{
T2* temp = new T2();
return temp;
}
int main()
{
Base* b = new Foo();
fun<Base,Foo>(b);
}
When there are extremely many classes deriving from the same base class then this code will save you from having to include clone methods every class. It's a more convenient way of cloning that involves templates and an intermediate subclass. It's doable if the hierarchy is shallow enough.
struct PureBase {
virtual Base* Clone() {
return nullptr;
};
};
template<typename T>
struct Base : PureBase {
virtual Base* Clone() {
return new T();
}
};
struct Derived : Base<Derived> {};
int main() {
PureBase* a = new Derived();
PureBase* b = a->Clone(); // typeid(*b) == typeid(Derived)
}