Let's say I have this base class for a data container:
class BaseClass{
public:
int a;
int getA();
void setA(int newA);
}
And I have a derived class:
class DerivedClass : BaseClass{
public:
int b;
int getB();
void setB(int newB);
}
Now I create two instances of the derived class:
DerivedClass* first = new DerivedClass();
DerivedClass* second = new DerivedClass();
Ok, here is my question:
How can I let second point to a deep copy of firsts object (without producing a memory leak)?
Also, I have to consider that the class / function which handles both pointers and wants to copy them isn't aware of the exact inheritated class. So those pointers could also point to another inheritance of BaseClass, and the copy function has to work still and copy all! members.
This code:
derivedClass x = *new derivedClass();
derivedClass y = *new derivedClass();
is a convoluted way to say:
derivedClass x = derivedClass();
derivedClass y = derivedClass();
putting new there only creates a memory leak and does not make x or y any different and would not make them "pointers" as you think. As for this:
*b = *a;
to work properly you should use a virtual function instead:
class Derived {
public:
virtual void copy_to( Base &b ) const override
{
if( Derived *d = dynamic_cast<Derived*>( &b ) )
*d = *this;
}
and call it like this:
a->copy_to( *b );
Of course copy_to needs to be defined and implemented in the base and every derived class.
Related
I have a base class which serves as an interface (if I use that word correctly). The idea is that the base class has some derived classes that implement one virtual function of the base class. Then I also need another class that extends the base class (lets call it extended base). What I would like is that I can store a class derived from base into an extended base pointer.
MWE:
class Base {
public:
virtual ~Base();
virtual double value();
}
class Derived : public Base{
public:
double value() override {return 5;}
}
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase ();
virtual double value2(){return 10;}
}
int main() {
ExtendedBase * object;
object = new Derived();
std::cout << object->value(); //should give implementation in Derived, i.e. 5
std::cout << object->value2(); //should give implementation in ExtendedBase, i.e. 10
delete object;
return 0;
}
With this MWE I get a compile error at the second line in the main. error: cannot convert 'Derived*' to 'ExtendedBase*' in assignment object = new Derived();. Part of me understands why it doesn't work (although I can't explain), but I would like to know if I can get the desired behaviour in some other way.
P.S. Sorry about the bad question name, I couldn't think of another way to keep it short
P.S.2 I know raw pointers like this are not advised. In the future I will change to smart pointers but I don't think they are needed for this simple example
ExtendedBase and Derived are each derived from Base. If you want to use an ExtendedBase* pointer to point to a Derived object, you will need to derive Derived from ExtendedBase.
To use a different example,
class Feline{
virtual void run();
}
class Housecat : Feline{
void run() {}
}
class BigCat : Feline{
virtual void run();
virtual void roar();
}
Here Feline, Housecat, and BigCat are analogous to Base, Derived, and ExtendedBase. BigCat and Housecat are each Feline, but since Housecat is not a BigCat, you can't use a BigCat* pointer to point to a Housecat.
This is the desired behavior from a language architect perspective.
For instance, if you have
class Ship
{
public:
virtual void move() = 0;
}
class Steamboat : public Ship
{
public:
virtual void move() override { ... }
}
class Sailboat : public Ship
{
public:
virtual void move() override { ... }
virtual void setSails() { ... }
}
Now, you don't want a Steamboat to become a Sailboat all of a sudden, hence:
Steamboat* tootoo = new Sailboat;
cannot be valid.
That's why your code cannot work. Conceptually.
So giving a quick fix is not possible, because your concept is not really clear.
When you are assigning an address to a pointer that means you should be able to access all the members of the type the pointer is pointing to through the pointer.
For ex,
class B {};
class D : B {};
B *p = new D();
now through p, at least you can access all the members of base portion of the derived class.
But in your code,
ExtendedBase * object;
object = new Derived();
object should be able to access all the members of ExtendedBase portion of the derived class. But how is it possible as derived class is not derived from ExtendeBase. So compiler is throwing error.
You need to do some changes in your code to work.
To make base as interface (abstract class), you need to define at
least one member function as pure virtual.
If you want to access the member function of ExtendedBase through
Base pointer, you should define same function 'val' in your
ExtendedBase.
Below are the changes.
#include <iostream>
using namespace std;
class Base {
public:
virtual ~Base() {};
virtual double value() = 0;
};
class Derived : public Base{
public:
~Derived() {};
double value() {
return 5;
}
};
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase () {};
double value()
{
return 10;
}
};
int main() {
Base *p = new Derived();
std::cout << p->value() << std::endl;
delete p;
Base *p1 = new ExtendedBase();
std::cout << p1->value() << std::endl;
delete p1;
return 0;
}
If I have a base class and a derived class, such as:
class Base {
protected:
int a;
public:
void setA(int);
void getA(int);
}
class Derived : public Base {
private:
int b;
public:
void doThing();
}
Then a third, additional class that uses the base class:
class OtherClass {
public:
Base doClassThing(Base*, Base*);
}
What's the best way to pass the derived class to a function that's defined to return a base class and take the base class as an argument. Like this:
Derived *x = new Derived();
Derived *y = new Derived();
doClassThing(x, y);
Would I pass the objects with a type cast? Or should I type cast the objects when they're first created?
To answer your two questions:
You would not cast the objects when they're first created.
There is no need to cast when calling; You do not need to modify the code in your question.
I've read
Passing pointer to derived class, to function that expects pointer to base class?
but the answer doesn't seem applicable to my issue.
I checked via Ideone that the following compiles, as it should:
class Base
{
public:
Base() {}
virtual ~Base() {}
};
class Derived : public Base
{
public:
Derived() {}
virtual ~Derived() {}
};
class Manager
{
public:
Manager(Base* b) {}
~Manager() {}
private:
Manager() {}
};
int main()
{
Derived* d = new Derived;
Manager* m = new Manager(d);
return 0;
}
However, what I believe is the same scenario in my actual program, produces an error (keywords have been replaced of course):
"main.cc", line 551: Error: Could not find a match for Manager::Manager(Derived*) needed in main().
I realize that posting explicit code would help, but the complexity of the code (not written by me, involving countless layers of inheritance, tens of includes per file, friend classes everywhere, extern'ed variables, etc.) is mind-numbing, and I'm not even sure what to reduce (what is relevant and what is not) to obtain something reasonable to post here.
I have one hint that may help. I found that casting to the base class beforehand works:
Manager* m = new Manager((Base*)d);
Of course, I shouldn't have to do that. But the fact that that works tells me that I haven't made some trivial mistake like forgetting a * in the constructor's signature.
Can anyone think of some possible reasons I could be getting the error that I'm getting, but not when I explicitly cast the derived instance to the base class?
I'm using Sun Studio 12 Update 1.
Additional Details
I don't know why this would matter, but in my real application I'm working with pointer pointers, e.g.
...
class Manager
{
public:
Manager(Base** b) {}
~Manager() {}
private:
Manager() {}
};
...
Derived* d = new Derived;
Derived** d_ptr = &d;
Manager* m = new Manager(&d_ptr);
So, to reiterate, the above works when I do the following.
Manager* m = new Manager((Base**)(&d));
Consider the following minimal example:
struct Base {};
struct Derived {};
int main()
{
Derived** ppD;
Base** ppB = ppD; // (A)
}
This code does not compile, because there's no implicit conversion in the line (A) to convert from Derived** to Base**. [conv.ptr]/3
A prvalue of type “pointer to cv D”, where D is a class type, can be converted to a prvalue of type “pointer to cv B”, where B is a base class of D. If B is an inaccessible or ambiguous base class of D, a program that necessitates this conversion is ill-formed.
This means that the conversion Base* pB = *ppD; is well-formed, but there's no implicit conversion for the case in line (A). Problems could occur if it was legal for example for multiple inheritance, virtual inheritance, or any other situation where the address of a pointer to an object of Derived has to be adjusted to get a pointer to the subobject of type Base.
Also consider the following scenario:
void f(Base** p)
{
delete *p;
*p = new Base;
}
int main()
{
Derived* pDerived = new Derived;
f(&p); // imagine this was allowed
// pDerived now points to an object of type Base!
}
Implicit conversion from pointer-to-derived to pointer-to-base does not extend to pointer-to-pointer-to-derived. You would get the same error if you tried this:
struct Base{};
struct Derived: Base {};
void f(Base **p){}
int main()
{
Derived *dp = 0;
f( &dp);
}
The following code will compile and work as the 'Derived' class is derived from the 'Base' class.
class Base
{
public:
Base() {}
virtual ~Base() {}
};
class Derived : public Base
{
public:
Derived() {}
virtual ~Derived() {}
};
class Manager
{
public:
Manager(Base* b) {}
~Manager() {}
private:
Manager() {}
};
int main()
{
Derived* d = new Derived;
Manager* m = new Manager(d);
return 0;
}
However, a pointer to a pointer to a 'Derived' class is not the same as (nor derived from) a pointer to a pointer to a 'Base' class.
For a great explanation involving bowls of bananas and apples, look here:
Conversion from Derived** to Base**
HTH.
Do either
Derived* d = new Derived;
Derived** d_ptr = &d;
Manager* m = new Manager(*d_ptr);
or
Derived* d = new Derived;
Derived** d_ptr = &d; // not needed ?
Manager* m = new Manager(d);
Ok heres some code.
#include <iostream>
#include <deque>
using namespace std;
class A
{
public:
virtual void Execute()
{
cout << "Hello from class A" << endl;
}
};
class B: public A
{
public:
void Execute()
{
cout << "Hello from class B" << endl;
}
};
void Main()
{
deque<A *> aclasses = deque<A*>(0);
deque<A *> aclasses2 = deque<A*>(0);
A a1 = A();
B b1 = B();
aclasses.push_back(&a1);
aclasses.push_back(&b1);
aclasses[0]->Execute();
aclasses[1]->Execute();
//Now say I want to copy a class from aclasses to aclasses2
//while perserving it's identity and making it a seperate entity, without
//knowing the exact type it is.
aclasses2.push_back(new A(*aclasses[0]));
aclasses2.push_back(new A(*aclasses[1]));
//Now my problem show itself
for each(A * a in aclasses2)
a->Execute();
//Execute is called from the original class A both times.
}
Now you might say, why don't you just put the pointers from the first deque into the second deque? While I could but I need the data to be independent. Basically I want to be able to clone items from the first deque while preserving there identity and giving them there own data.
Now the current modified version
#include <iostream>
#include <deque>
using namespace std;
class A
{
public:
virtual void Execute()
{
cout << "Hello from class A" << endl;
}
virtual ~A() {} // don't forget the virtual destructor
virtual A* clone() const {
return new A(*this);
}
};
class B: public A
{
public:
void Execute()
{
cout << "Hello from class B" << endl;
}
virtual B* clone() { // return type is co-variant
return new B( *this );
}
};
void MainRUNNER()
{
deque<A *> aclasses = deque<A*>(0);
deque<A *> aclasses2 = deque<A*>(0);
A a1 = A();
B b1 = B();
aclasses.push_back(&a1);
aclasses.push_back(&b1);
aclasses[0]->Execute();
aclasses[1]->Execute();
//Now say I want to copy a class from aclasses to aclasses2
//while perserving it's identity and making it a seperate entity, without
//knowing the exact type it is.
aclasses2.push_back(aclasses[0]->clone());
aclasses2.push_back(aclasses[1]->clone());
//Now my problem show itself
for each(A * a in aclasses2)
a->Execute();
//Execute is called from the original class A both times.
}
The common pattern for handling that is through a virtual clone() method in the base class that will create a new object of the appropriate type:
struct base {
virtual ~base() {} // don't forget the virtual destructor
virtual base* clone() const {
return new base(*this);
}
};
struct derived : base {
virtual derived* clone() const { // return type is co-variant
return new derived( *this );
}
};
int main() {
std::auto_ptr<base> b1( new derived );
std::auto_ptr<base> b2( b1->clone() ); // will create a derived object
}
You need to provide a virtual copy constructor – usually this is a method called clone – which is overridden in each class to return the correct type:
class A {
virtual A* clone() {
return new A();
}
};
class B : public A {
void A* clone() {
return new B();
}
};
The methods can of course be arbitrarily complex in order to copy the whole state.
Of course, this leaks rather a lot of memory. Use appropriate smart pointers instead of raw pointers (e.g. std::shared_ptr if your compiler supports it, boost::shared_ptr otherwise).
You have new A(...) way down there. What gets called is A's copy constructor (created implicitly by the compiler.
What you want is a clone method. See here. It recaps the appropriate item from the excellent C++ Coding Standards book. Below is a shameless copy of the final solution, which also shows a nice use of the NVI idiom to avoid the slicing problem.
class A {// …
public:
A* Clone() const { // nonvirtual
A* p = DoClone();
assert( typeid(*p) == typeid(*this) && "DoClone incorrectly overridden" );
return p; // check DoClone's returned type
}
protected:
A( const A& );
virtual A* DoClone() const = 0;
};
class B : public A { // …
public:
virtual B* Clone() const {return new B(*this); }
protected:
B( const B& rhs ) : A( rhs ) {/* … */}
};
update
A bit of an explanation. The basic idea of the clone is the same as the other excellent answers here.
Now, with cloning you have the danger of slicing objects. For example, if some object which derives from A forgets to implement its own clone method, then a call to A* a = d->clone() will not return a full D object (assuming D is a descendant of A)
The NVI idiom says to separate a public interface from a virtual interface. Thus, in this example, clone is public, but not virtual. It call a protected virtual method, doClone, which does the actual cloning, and which derived objects also implement. Because of the split, the clone method can verify that the type of the cloned object matches the type of the original object.
I think you confuse classes with objects, i.e. instances of those classes.
Your container aclasses store pointers to existing objects. You may take the same pointer and push it several times in many different containers, this is not called cloning.
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();
}