let's say I have a pointer to some base class and I want to create a new instance of this object's derived class. How can I do this?
class Base
{
// virtual
};
class Derived : Base
{
// ...
};
void someFunction(Base *b)
{
Base *newInstance = new Derived(); // but here I don't know how I can get the Derived class type from *b
}
void test()
{
Derived *d = new Derived();
someFunction(d);
}
Cloning
struct Base {
virtual Base* clone() { return new Base(*this); }
};
struct Derived : Base {
virtual Base* clone() { return new Derived(*this); }
};
void someFunction(Base* b) {
Base* newInstance = b->clone();
}
int main() {
Derived* d = new Derived();
someFunction(d);
}
This is a pretty typical pattern.
Creating new objects
struct Base {
virtual Base* create_blank() { return new Base; }
};
struct Derived : Base {
virtual Base* create_blank() { return new Derived; }
};
void someFunction(Base* b) {
Base* newInstance = b->create_blank();
}
int main() {
Derived* d = new Derived();
someFunction(d);
}
Though I don't think that this a typical thing to do; it looks to me like a bit of a code smell. Are you sure that you need it?
It's called clone and you implement a virtual function that returns a pointer to a dynamically-allocated copy of the object.
Related
I am trying to make a deep copy of the object d of class Derived as in the code below:
class A {
public:
int m_int;
A* clone() {
return new A(*this);
}
};
class Base {
public:
A* m_a;
virtual Base* clone() {
A* new_a = new A();
new_a = this->m_a->clone();
Base* clone = new Base(*this);
clone->m_a = new_a;
return clone;
}
};
class Derived : public Base {
public:
double m_dbl;
virtual Derived* clone() {
return new Derived(*this);
}
};
int main() {
Derived* d = new Derived();
d->m_dbl = 1.234;
A* a = new A();
a->m_int = -1;
d->m_a = a;
//clone d
Derived d_copy = d->clone();
//changing values of d's attributes must not affect d_copy
a->m_int = 10;
d->m_dbl = 3.456;
//check d_copy
cout << "m_int " << d_copy->m_a->m_int << endl;
cout << "m_dbl " << d_copy->m_dbl << endl;
}
output:
m_int 10 //wrong, should be -1;
m_dbl 1.234 //correct
As you can see, simply returning new Derived(*this) in Derived's clone() method is wrong since it does not deep-copy m_a.
If I "bring down" the deep-copying of m_a from Base to Derived then I will get the correct answer:
virtual Base* clone() = 0;
...
virtual Derived* clone() {
A* new_a = new A();
new_a = this->m_a->clone();
Derived* clone = new Derived(*this);
clone->m_a = new_a;
return new Derived(*this);
}
//gives out m_int = -1
If this is the case does this mean that each time I create further derived classes from Derived, I always have to "bring down" the contents of clone() to them?
Also, if for example Base has two derived classes Derived1 and Derived2, does this mean that I have to deep-copy the members of Base in each of them?
Any other ways to approach this?
You can consider of implementing the copy constructor that always is doing deep copy. In such case your clone implementation will always be trivial:
class Base {
public:
A* m_a;
Base(const A& other)
: m_a(other.m_a->clone())
{
}
virtual Base* clone() {
return new A(*this);
}
};
class Derived : public Base {
public:
double m_dbl;
Derived(const Derived& other)
: m_dbl(other.m_dbl)
virtual Derived* clone() {
return new Derived(*this);
}
};
If you don't want to change the behavior of the default constructor (you want the default constructor to make shallow copy for example) the alternative is to move copy implementation to a CopyTo method, so you can reuse it:
class Base {
public:
A* m_a;
static void CopyTo(const Base& from, Base& to)
{
to.m_a = from.m_a->clone();
}
virtual Base* clone() {
Base* result = new Base();
CopyTo(*this, result);
return result;
}
};
class Derived : public Base {
public:
double m_dbl;
static void CopyTo(const Base& from, Base& to)
{
Base::CopyTo(from, to);
to.m_dbl= from.m_dbl;
}
virtual Derived * clone() {
Derived * result = new Derived ();
CopyTo(*this, result);
return result;
}
virtual Derived* clone() {
return new Derived(*this);
}
};
I have an object that is referenced by a pointer to its superclass: Base* d1 = new Derived();
I would like to pass it to another method that expects an object of the derived class: void f(Derived* d);
But it doesn't work unless I use type-casting. Is there another way to achieve this?
Here is an example:
#include <stdio>
class Base {};
class Derived : public Base {};
class Client
{
public:
void f(Base* b) { printf("base"); };
void f(Derived* d) { printf("derived"); };
};
int main(int argc, char* argv[])
{
Client* c = new Client();
Base* b = new Base();
Base* d1 = new Derived();
Derived* d2 = (Derived*) d1;
c->f(b); // prints "base". Ok.
c->f(d1); // prints "base"! I expected it to be "derived"!
c->f(d2); // prints "derived". Type-casting is the only way?
}
Generally speaking, you can do some stuff with dynamic_cast.
From the other side I believe, that dynamic_cast can practically always be avoided by the good design.
In your example you can make function f virtual member of Base class and override it in the Derived class. Then call it f via pointer to Base.
Something like this:
class Base {
public:
virtual void f() {
printf("Base\n");
}
};
class Derived : public Base {
public:
virtual void f() {
printf("Derived\n");
}
};
class Client
{
public:
void f(Base* b) {
b->f();
};
};
class Base {
public:
virtual Base* clone() const { return new Base(*this); }
// ...
};
class Derived: public Base {
public:
Derived* clone() const override { return new Derived(*this); }
// ...
};
int main() {
Derived *d = new Derived;
Base *b = d;
Derived *d2 = b->clone();
delete d;
delete d2;
}
i compile above code in the latest version of Xcode, and compiler complains
cannot initialize a variable of type "Derived*" with an rvalue of type "Base*"*
at Derived *d2 = b->clone().
But I already make clone virtual and let the clone() in Derived return Derived *.
Why do I still have such problem?
The return type of Base::clone() is Base*, not Derived*. Since you are invoking clone() through a Base*, the expected return value is a Base*.
If you invoke clone() through a Derived*, you will be able to use the return type of Derived::clone().
Derived *d = new Derived;
Derived *d2 = d->clone(); // OK
Also,
Base *b = d;
Derived *d2 = dynamic_cast<Derived*>(b->clone()); // OK
Also,
Base *b = d;
Derived *d2 = dynamic_cast<Derived*>(b)->clone(); // OK
Say I have a base class Base, and two derived classes Derived: public Base and Derived2: public Base.
I have a purely virtual function
virtual int CompareByInsertKey( Base* item_in_list ) = 0;
In class Base. So it's a function that takes a pointer to a Base class.
I want my class Derived to overwrite this virtual function but I want it to take a pointer to a Derived class as an argument.
I also want my class Derived2 to overwrite this function but I want to to take a pointer to the Derived2 class as an argument.
Does it do this automatically if I keep the argument as Base* item_in_list because Derived and Derived2 are part Base classes?
If not, how do I do this?
Thanks, if you need me to post more information, please comment.
it takes pointers to the derived classes automatically because Derived * is implicitly convertible to Base *. You will have to implement it using Base in the function argument in order to override the function though.
virtual int CompareByInsertKey( Base* item_in_list ) override
{
Derived *ptr = dynamic_cast<Derived *>(item_in_list);
// ...
}
The compiler cannot do what are hoping to do.
struct Base
{
virtual int CompareByInsertKey( Base* item ) = 0;
};
struct Derived : Base
{
virtual int CompareByInsertKey( Base* item )
{
return 1;
}
};
struct Derived2 : Base
{
virtual int CompareByInsertKey( Base* item )
{
return 2;
}
};
int main()
{
Base* d1 = new Derived;
Base* d2 = new Derived2;
d1->CompareByInsertKey(d2); // This is a valid call
// but the argument is not of type Derived*
}
In order for the function signatures to match you have to use Base* in CompareByInsertKey. Unfortunately, that means you could pass a Derived as the parameter on a Derived2. Maybe templates would work better for your app.
Try running the following example.
#include "stdafx.h"
using namespace std;
class Base {
public:
string name;
Base(string n) : name(n) {}
virtual int CompareByInsertKey(Base* item_in_list) = 0;
virtual string Name() { return name; }
};
class Derived : public Base
{
public:
Derived() : Base("derived") {}
int CompareByInsertKey(Base *item_in_list)
{
cout << "In Derived, parameter is " << item_in_list->Name() << endl;
return 0;
}
};
class Derived2 : public Base
{
public:
Derived2() : Base("derived2") {}
int CompareByInsertKey(Base *item_in_list)
{
cout << "In Derived2, parameter is " << item_in_list->Name() << endl;
return 0;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Base * d2 = new Derived2();
Base *d = new Derived();
d2->CompareByInsertKey(d);
return 0;
}
KC
You can do this via a more complicated structure and knowledge about the types
class Base
{
public:
int publicComparator(Base* instance)
{
// you can use either typeid() or your on enum that you put in the
// hierarchy
if (typeid(this) == typeidf(instance))
{
return privateComparator(instance);
}
return ErrorCode;
}
private:
virtual privateComparator(Base *instance) = 0;
}
class Dervied : public Base {
private:
privateComparator(Base* instance) override {
// The assumption is privateComparator is only called when this cast
// can sucessfully be completed
Derived* derivedInstance = static_cast<Derived*>(instance);
// Do functionality
return result;
}
}
So with this if you call a->publicComparator(b)' only when the type ofaandb` are the same will the derived function actually be executed, is that the functionality that you where looking for ?
I know there are solved questions related to this issue, but I still can't figure out how to resolve my problem.
I have something like this:
class Base
{
static Base* createBase()
{
Base *b = new Base();
... //does a lot of weird things
return b;
}
}
class Child : public Base
{
static Child* createChild()
{
Child *c = createBase(); // error
return c;
}
}
I know why it doesn't work, but I have to find a way to do it. The createBase function does a lot of things so I don't want to recode it.
Any suggestions?
Why do you expect that to work? You can't treat a Base object as if it were a Child object, because the Child class might have all sorts of additional data that Base does not.
In order to get the effect you're looking for, there are two ways to do it:
The first way, and probably the best idea, is to move the logic from createBase into the Base constructor. The Base constructor will run whether you're creating a Base or something derived from it. It looks like you're trying to do the work of initializing the base object, and that's exactly what constructors are for!
If for some reason this will not work in your case, the other option is to create a protected initialize method in Base which accepts a Base* and does all the work that you are currently doing in createBase, e.g.
class Base
{
public:
static Base* createBase()
{
Base* b = new Base();
initialize(b);
return b;
}
protected:
static void initialize(Base* b)
{
... //does a lot of weird things
}
}
class Child : public Base
{
public:
static Child* createChild()
{
Child *c = new Child();
initialize(c):
return c;
}
}
Note that this works since, while you can't treat a Base* as if it were a Child*, you can go the other way and treat a Child* as if it were a Base*, because the Child class is guaranteed to have at least everything that the Base class does, due to the nature of inheritance.
Edit: I saw you post in a comment to another answer that you cannot modify the definition of Base. In that case, you are completely out of luck and you will have to accept the need to copy-and-paste, given the restrictions in play. You are not going to be able to call createBase and get back a pointer to an object of any type other than Base if you cannot modify its code.
overloading new for Base class might solve your issue.
class UTIL{
static size_t size;
public:
static void setSize(size_t t)
{
//mutex protection
size = t;
}
static size_t getsize(); // should only be called from inside new of class A
};
class A
{
int i;
public:
static A* createA()
{
A* a = new A();
a->i = 10;
return a;
}
void* operator new (size_t size) throw (const char *){
void * p = malloc(UTIL::getsize());
if (p == 0) throw "allocation failure";
return p;
}
void operator delete (void *p){
free(p);
}
};
size_t UTIL::size = sizeof(A);
size_t UTIL::getsize()
{
//mutex protection
size_t tmp = size;
size = sizeof(A);
return tmp;
}
class B
{
public:
int j;
static B* createB()
{
//take mutex
UTIL::setSize(sizeof(B));
B* b = (B*)(A::createA());
b->j = 20;
//release Mutex
return b;
}
};
Perhaps you should re-define createBase as follows:
template< class TheClass > static TheClass* create()
{
TheClass *ret = new TheClass();
... //does a lot of weird things
return ret;
}
You can then create an object as follows:
Child* pChild = create< Child >();
This may not be appropriate depending what the "weird" things are but its one possible way of solving your issues.
You should be using
Child *c = new Child();
Otherwise you are trying to create a Base class instance and call it a Child.
RE your comment:
Perhaps you could change
static Base* createBase();
static void createBase(Base *b);
If you pass the instance into this method you could use it with both Child and Base
for example:
Base *b = new Base();
Base::createBase(b);
Child *c = new Child();
Base::createBase(c);
or alternatively
static Base *createBase(Base *b = NULL){
if(b == NULL){
b = new Base;
}
//do your stuff
return b;
and for the child:
static Child* createChild(){
Child *c = new Child;
createBase(c);
return c;
This way you can use both:
b = Base::createBase();
c = Child::createChild();
Don't the "weird" things belong in the Base constructor. Then by constructing the Child your base gets properly constructed?
Otherwise just refactor the code into a method you call from both places - definately don't copy it.
You can use constructors to do the work for you:
class Base
{
Base()
{
// does a lot of weird things
}
static Base* createBase()
{
return new Base();
}
};
class Child : public Base
{
Child()
{
// Do child's weird things here
}
static Child* createChild()
{
return new Child();
}
};
Base *instance1 = new Child(); // Works as expected
Base *instance2 = Child::createChild(); // Works as expected
Base *instance3 = new Base(); // Works as expected
Base *instance4 = Base::createBase(); // Works as expected
EDIT:
If you can't modify the Base class, you shouldn't derive from it this way. The class is apparently meant to have its own functionality and the static construction method suggests some more complex usage. You might want to use the Decorator design pattern instead of inheritance in this case: http://en.wikipedia.org/wiki/Decorator_pattern
how about this
class Base
{
public:
static Base* createBase()
{
Base *b = new Base();
//does a lot of weird things
return b;
}
};
class Child
{
protected:
Base* m_basePtr;
public:
operator Base&(){return *m_basePtr;}
static Child* createChild()
{
Child *c=new Child;
c->m_basePtr=Base::createBase();
return c;
}
};
but you have to delete the pointer at the destructor
What you want to do is:
class Base
{
Base()
{
... //does a lot of weird things
}
};
class Child : public Base
{
Child Child() // This calls the base constructor auto-magically
{
}
}
int main()
{
Child childOne;
Base baseOne;
Child* childPtr = new Child();
Base* basePtr1 = new Child();
Base* basePtr2 = new Base();
}