I have a class with a vector as below:
#include <vector>
class Base{};
class Derived: public Base{};
class Foo{
private:
std::vector<Base*> vec;
public:
Foo() = default;
void addObject(const Base* b){
// vec.push_back(new Base(*b));
// vec.push_back(new Derived(*b));
}
};
int main(){
Derived* d = new Derived();
Base* b = new Base();
Foo f;
f.addObject(d);
f.addObject(b);
delete d;
delete b;
return 0;
}
The function addBase may receive Derived's pointers. The line vec.push_back(new Base(b)); is expected to use b's copy to initialize a new object whose pointer will be pushed_back. If I don't use new, I will have resources shared between b and the vector(This is a sin).
I want to maintain polymorphism. How do I ensure objects that are pushed back maintain the type they were assigned during their creation without forcing everything into a Base object.
If you want to create a clone of the object passed to addObject, you have essentially two options. 1) Have a virtual function clone in Base and Derived, or better 2) let the copy constructor handle it.
If you go for the second option, addObject need to the know the actual type of the passed object. This could be done with a template:
template <class T>
void addObject(const T * t)
{
Base *b = new T(*t);
}
In a robust program we don't want to use new/delete but rather std::unique_ptr or std::shared_ptr. Passing t as a reference, rater than pointer, is also considered a better practice.
#include <vector>
#include <memory>
#include <iostream>
class Base
{
public:
virtual void cname() { std::cout << "Base" << std::endl;}
};
class Derived: public Base
{
public:
virtual void cname() { std::cout << "Derived" << std::endl;}
};
class Foo
{
private:
// You may switch to `std::shared_ptr` if that better fits your use case
std::vector<std::unique_ptr<Base> > vec;
public:
template <class T>
void addObject(const T & t)
{
vec.push_back(std::make_unique<T> (t));
}
void dump()
{
for (auto &bp: vec)
bp->cname();
}
};
int main(){
Derived d;
Base b;
Foo f;
f.addObject(d);
f.addObject(b);
f.dump();
return 0;
}
Naturally for this to work, the reference passed to addObject must be of the correct type. This will create a clone of type Base, not Derived:
Derived d;
Base &e = d;
f.addObject(e);
Related
I have base-class Base from which is derived Derived1, Derived2 and Derived3.
I have constructed an instance for one of the the derived classes which I store as Base* a. I now need to make a deep copy of the object which I will store as Base* b.
As far as I know, the normal way of copying a class is to use copy constructors and to overload operator=. However since I don't know whether a is of type Derived1, Derived2 or Derived3, I cannot think of a way of using either the copy constructor or operator=. The only way I can think of to cleanly make this work is to implement something like:
class Base
{
public:
virtual Base* Clone() = 0;
};
and the implement Clone in in the derived class as in:
class Derivedn : public Base
{
public:
Base* Clone()
{
Derived1* ret = new Derived1;
copy all the data members
}
};
Java tends to use Clone quite a bit is there more of a C++ way of doing this?
This is still how we do stuff in C++ for polymorphic classes, but you don't need to do the explicit copy of members if you create a copy constructor (possibly implicit or private) for your objects.
class Base
{
public:
virtual Base* Clone() = 0;
};
class Derivedn : public Base
{
public:
//This is OK, its called covariant return type.
Derivedn* Clone()
{
return new Derivedn(*this);
}
private:
Derivedn(const Derivedn&) : ... {}
};
template <class T>
Base* Clone (T derivedobj) {
T* derivedptr = new T(derivedobj);
Base* baseptr = dynamic_cast<Base*>(derivedptr);
if(baseptr != NULL) {
return baseptr;
}
// this will be reached if T is not derived from Base
delete derivedptr;
throw std::string("Invalid type given to Clone");
}
The only thing this function requires of the derived classes is that their copy constructor is publicly accessible.
I have seen some answers using a template function to clone objects. Let me show you how that will not work. Consider the following code:
This is a special case that shows up when objects are being received from a container of Base objects. The function will return a pointer to the Base even when obj is of type Derived. The template only works when it is called by an object that has not undergone any casting.
#include <iostream>
#include <memory>
#include <vector>
class Base{
public:
virtual void foo(){}
};
class Derived : public Base{};
template<typename T> std::shared_ptr<T> foo(const T& obj){
std::cout << "obj is of type: " << typeid(obj).name() << std::endl;
std::cout << "T is of type: " << typeid(T).name() << std::endl;
std::cout << std::endl;
return std::make_shared<T>(obj); // returns Base pointer
}
int main()
{
std::vector<std::shared_ptr<Base>> vec {std::make_shared<Base>(), std::make_shared<Derived>()};
for(auto c: vec)
foo(*c);
return 0;
}
/* OUTPUT:
obj is of type: 4Base
T is of type: 4Base
obj is of type: 7Derived
T is of type: 4Base
*/
I have a class A with child class B, and want to make a template function to call virtual functions of A and B:
#include <stdio.h>
class A{
public:
virtual void test(){
printf("A\n");
}
};
class B:public A{
public:
virtual void test(){
printf("B\n");
}
};
template<class T>
void f(T t){
t.test();
}
int main(){
A* a=new B();
f<A>(*a);
return 0;
};
it prints A only and seems does not override test(), but when I change
void f(T t)
to
void f(T& t)
like that:
#include <stdio.h>
class A{
public:
virtual void test(){
printf("A\n");
}
};
class B:public A{
public:
virtual void test(){
printf("B\n");
}
};
template<class T>
void f(T& t){
t.test();
}
int main(){
A* a=new B();
f<A>(*a);
return 0;
};
,it prints B, why would that happen?
When you use
template<class T>
void f(T t){ ... }
your code suffers from object slicing. You construct a B but only the A part of the object gets passed to f.
That does not happen when you use
template<class T>
void f(T& t){ ... }
Over-riding is achieved by using Pointers or References. Please do read a good article regarding polymorphism.
Happy coding.
When you call f(T t), c++ actually new an object of T by constructor T(T& t). Then the reference of this object is passed into function.
You call write code to prove it
class A {
public:
int x;
A():x(6){
}
A(A& a) {
x = 2;
}
virtual void test() {
printf("%d\n", x);
}
};
class B : public A {
public:
virtual void test() {
printf("%d\n", x);
}
};
void fun(A a)
{
a.test();
}
void f(A& a)
{
a.test();
}
int main(void)
{
A* a = new A();
A* b = new B();
A* c = new A(*b);
fun(*a);
fun(*b);
f(*a);
f(*b);
f(*c);
}
the output is 2 2 6 6 2
How you have your class hierarchy defined is that class B is derived from class A. So when class B's constructor is called it must call A's constructor first before it can be constructed. Both A & B have the same exact virtual function or definition called test().
With your first implementation of f() your template will deduce the parameter type while it is being compiled. It is looking for a class type where in main when you invoke the template function you are telling this template function to expect a type of class A. This will then use A::test() to call the test function. In your main function before you invoke f() you are creating a pointer of type class A dynamically and placing it in the heap, but you are using B's constructor which is a derived type of A. This will use B's constructor to call A's constructor. Your template function is expecting type A so it is invoking a.test() or A::test() in your code.
In your second declaration or definition of f() your classes are defined the same and behave the exact same way. What is different this time is your template function that will be resolved during compilation to deduce its parameter's type. In this version of the function it is expecting the address of class type A since now that it is expecting a memory address as opposed to the actual variable itself, this time when you instantiate or invoke the function f() where it expects a parameter of type T& it is now using the referencing capabilities of c++ and it now invokes b.test().
If you want to see why this is happening use your first declaration of f() and set a break point where you have A* a = new B(); and step into the code line by line, don't step over, but into. Then do the same exact process with your second version of f() and you will see what is happening.
This isn't because the class is or isn't overriding the virtual function; this is due to how template functions work.
Now my question is why would you want to create a pointer for a base type and setting new memory for it by calling its derived type's constructor.
Normally with polymorphism and abstract classes you would usually create a type of derived but you may have a container that holds pointers to the base class of derived where you would normally cast them dynamically. For example let us say that you have a base class of Automobile which is abstract; meaning you can not create this class directly because it's constructor is protected where only derived types can have access to it. Now a derived type might be Car, Van, Truck, SUV, Jeep, MotorCycle and in some other class or function you may have a vector<shared_ptr<Automobile>> stored. So this way you can push a smart pointer of a truck, a car, and a van, all into the same container by dynamically casting these constructed objects pointers to their Base type Automobile since they all publicly inherit from them! However when working with abstract types special care needs to be used.
Check out this little program to see how polymorphism works (there are no abstract types here)
#include <conio.h>
#include <string>
#include <iostream>
#include <vector>
#include <memory>
class Base {
public:
Base() {}
virtual ~Base(){}
virtual void test() const { std::cout << "Base" << std::endl; }
};
class DerivedA : public Base {
public:
DerivedA() : Base() {}
virtual ~DerivedA() {}
virtual void test() const override { std::cout << "DerivedA" << std::endl; }
};
class DerivedB : public Base {
public:
DerivedB() : Base() {}
virtual ~DerivedB() {}
virtual void test() const override { std::cout << "DerivedB" << std::endl; }
};
template<class T>
void f( T t ) {
t.test();
}
template<class T>
void g( T& t ) {
t.test();
}
int main() {
DerivedA* a = new DerivedA();
//f<DerivedA>( *a );
//g<DerivedA>( *a );
DerivedB* b = new DerivedB();
//f<DerivedB>( *b );
//g<DerivedB>( *b );
std::vector<Base*> vBases;
vBases.push_back( a );
vBases.push_back( b );
for ( unsigned i = 0; i < vBases.size(); ++i ) {
if ( i == 0 ) {
std::cout << "First Iteration: i = " << i << std::endl;
} else if ( i == 1 ) {
std::cout << "Second Iteration: i = " << i << std::endl;
}
f<DerivedA>( *dynamic_cast<DerivedA*>( vBases[i] ) );
f<DerivedB>( *dynamic_cast<DerivedB*>( vBases[i] ) );
std::cout << std::endl;
g<DerivedA>( *static_cast<DerivedA*>( vBases[i] ) );
g<DerivedB>( *static_cast<DerivedB*>( vBases[i] ) );
std::cout << std::endl;
}
delete a; // You Forgot To Delete Your Dynamic Pointers - Memory Leak!
delete b;
std::cout << "Press any key to quit" << std::endl;
_getch();
return 0;
}
Output
DerivedA
DerivedB
DerivedA
DerivedA
DerivedA
DerivedB
DerivedB
DerivedB
Maybe this will help you to understand what is happening with your two different template types by using a dynamic_cast<> for f<>() your first version of your template function and using static_cast<> for g<>() for your second version of your template function that takes a reference instead of a stack copy of a variable.
If you remember there are two elements in this vector the first being a DerivedA* and the second being a DerivedB* both which are of a type Base and are stored as a Base* in the vector. The first 4 lines of out put is work that is done on the first element of our vector only! The last 4 lines of out put is work that is done on the second element of our vector only!
Our first stored element at index 0 is of a DerivedA type stored as a Base* and the first call to f<>() we dynamically cast it to a DerivedA* type and we then dereference the pointer. The second call to f<>() we do the same thing except we dynamically cast it to a DerivedB* type and deference it. So here this first stored object is invoking DerivedA::test() then it is invoking DerivedB::test() by using the dynamic cast.
The next two lines are still working on the same element which is our DerivedA* stored as a Base*at index 0 in our vector. This time we are now using g<>() your second method of your function template, and instead of using a dynamic_cast<> we are now using a static_cast<> since g<>() is expecting a reference to an object and not a stack variable itself. If you notice this time around nothing gets casted from one type to another and our function template is always invoking DerivedA::test() even though on the second call to this method we are telling it to cast it to a <DerivedB> type.
For the next 4 lines of output we are now working with our 2nd stored object in the vector at index 1 but this time our saved object is of a DerivedB type stored as a Base*. On the next two lines we have the same output as in the first iteration. This time DerivedB is being casted to a DerivedA for the first call to f<>() and remains its own type for the second call to f<>() and for the final two lines as you can see the stored object at index 1 that is of a DerivedB type stored as a Base* is not being changed or casted to a DerivedA type on the first call of g<>().
I have a function that looks like:
// this function might modify base_ptr
void SomeFunction(shared_ptr<Base> &base_ptr)
{ if(some_condition) { base_ptr = some_other_ptr; } }
I'd like to call the function with a shared_ptr:
shared_ptr<Derived> d = ...;
SomeFunction(d);
This doesn't work though. It doesn't work if I'm using normal pointers either (ie. implicit casting to Base* & from Derived*. One workaround is to create a Base pointer from the Derived one, and then pass that to the function.
shared_ptr<Base> base = d;
SomeFunction(b);
But this isn't very pretty from a coding standpoint. It also adds confusion and the potential for a subtle bug:
shared_ptr<Derived> d = derived;
shared_ptr<Base> b = derived;
SomeFunction(b);
// b and d might now be pointing to different things -- not good!
Is there better way to do this?
What you are trying to do is inherently dangerous, and C++ is making it hard on purpose. Consider if C++ allowed you to call SomeFunction the way you wanted. Then you could do this:
struct Base {
};
struct Derived1 : Base {
void f1();
};
struct Derived2 : Base {
void f2();
};
void SomeFunction(shared_ptr<Base> &p)
{
p = make_shared<Derived2>(); // nothing wrong with converting
// a Derived2 pointer to a Base pointer.
}
int main()
{
shared_ptr<Derived1> d = make_shared<Derived1>();
SomeFunction(d); // An error, but what if it wasn't?
d->f1(); // Trying to call method f1 of a Derived2!
}
The compiler would not be able to know that d changed from a Derived1 pointer to a Derived2 pointer, so it wouldn't be able to give you a compile error when you tried to call method f1 of a Derived2.
You could template the function for the smart pointer's type
#include <iostream>
#include <memory>
#include <type_traits>
using namespace std;
class Base {
public:
virtual void hello() {
cout << "hello base" << endl;
}
};
class Derived : public Base {
public:
void hello() {
cout << "hello derived" << endl;
}
};
class otherClass {
public:
};
template<typename T>
void SomeFunction(shared_ptr<T> &base_ptr)
{
static_assert(is_base_of<Base, T>::value == true, "Wrong non-derived type");
base_ptr->hello();
// Rebase it
base_ptr.reset(new Derived);
base_ptr->hello();
}
int main() {
shared_ptr<Base> obj(new Base());
SomeFunction(obj);
// hello base
// hello derived
shared_ptr<Derived> obj2(new Derived());
// hello derived
// hello derived
SomeFunction(obj2);
shared_ptr<otherClass> obj3(new otherClass());
SomeFunction(obj3); // ASSERT
return 0;
}
http://ideone.com/ATqhEZ
If you intend to update all the smart pointers when you reset one, you'll have to do some book-keeping by yourself since they're not designed to have a "signal-like" mechanism to notify other smart pointers pointing to the same object.
Edited my answer to provide compile-time safety if you intend to use it with Base and relative subclasses.
Warning: the above solution uses C++11, the same could be accomplished in a similar way in pre-C++11 code
I have base-class Base from which is derived Derived1, Derived2 and Derived3.
I have constructed an instance for one of the the derived classes which I store as Base* a. I now need to make a deep copy of the object which I will store as Base* b.
As far as I know, the normal way of copying a class is to use copy constructors and to overload operator=. However since I don't know whether a is of type Derived1, Derived2 or Derived3, I cannot think of a way of using either the copy constructor or operator=. The only way I can think of to cleanly make this work is to implement something like:
class Base
{
public:
virtual Base* Clone() = 0;
};
and the implement Clone in in the derived class as in:
class Derivedn : public Base
{
public:
Base* Clone()
{
Derived1* ret = new Derived1;
copy all the data members
}
};
Java tends to use Clone quite a bit is there more of a C++ way of doing this?
This is still how we do stuff in C++ for polymorphic classes, but you don't need to do the explicit copy of members if you create a copy constructor (possibly implicit or private) for your objects.
class Base
{
public:
virtual Base* Clone() = 0;
};
class Derivedn : public Base
{
public:
//This is OK, its called covariant return type.
Derivedn* Clone()
{
return new Derivedn(*this);
}
private:
Derivedn(const Derivedn&) : ... {}
};
template <class T>
Base* Clone (T derivedobj) {
T* derivedptr = new T(derivedobj);
Base* baseptr = dynamic_cast<Base*>(derivedptr);
if(baseptr != NULL) {
return baseptr;
}
// this will be reached if T is not derived from Base
delete derivedptr;
throw std::string("Invalid type given to Clone");
}
The only thing this function requires of the derived classes is that their copy constructor is publicly accessible.
I have seen some answers using a template function to clone objects. Let me show you how that will not work. Consider the following code:
This is a special case that shows up when objects are being received from a container of Base objects. The function will return a pointer to the Base even when obj is of type Derived. The template only works when it is called by an object that has not undergone any casting.
#include <iostream>
#include <memory>
#include <vector>
class Base{
public:
virtual void foo(){}
};
class Derived : public Base{};
template<typename T> std::shared_ptr<T> foo(const T& obj){
std::cout << "obj is of type: " << typeid(obj).name() << std::endl;
std::cout << "T is of type: " << typeid(T).name() << std::endl;
std::cout << std::endl;
return std::make_shared<T>(obj); // returns Base pointer
}
int main()
{
std::vector<std::shared_ptr<Base>> vec {std::make_shared<Base>(), std::make_shared<Derived>()};
for(auto c: vec)
foo(*c);
return 0;
}
/* OUTPUT:
obj is of type: 4Base
T is of type: 4Base
obj is of type: 7Derived
T is of type: 4Base
*/
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)
}