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();
}
Related
I'd like to achieve something like this below:
class A {
public:
virtual void reset() {
// 1). if there's no override to this function,
// then whatever derived from A should get reset
// to its constructed state, e.g. if B derives from
// A, then *this = B();
// 2). if there is an override to reset in the derived
// class, call the reset in the derived class
}
};
class B: public A {
public:
B() { std::cout<<"reset B"<<std::endl; }
// no override of reset() here
};
class C: public A {
public:
void reset() override {
std::cout<<"reset C"<<std::endl;
}
};
N.B. A doesn't know which class will derive from it, but whoever derive from it, if there is no reset() override in that derived class, calling A::reset() should reset the derived class object to its constructed state, i.e.
A* a = new B();
a->reset(); // -> this equals to *a = B();
However, if there is an override of reset() in the derived class, calling A::reset() should call the overridden reset(), i.e.
A* a = new C();
a->reset(); // -> this should call C::reset()
As mentioned in my comment it can be solved with the help of the CRTP, and another level of inheritance:
// The base class is just an abstract interface class
struct A
{
virtual void reset() = 0;
};
template<typename T>
struct realA : public A
{
void reset() override
{
*this = T();
}
}
class B : public realA<B>
{
... whatever you need here...
};
Now you can do
A* a = new B;
a->reset();
and it should work as you seemingly want it.
You have the (now abstract) base class A which contains the interface needed. Then you have the template class realA which contains the implementation you have in your variant of the A class, most notably the reset function implementation. Then the classes like B (and C and others) which inherits from realA instead of A.
Apart from the accepted answer, there is an alternative approach.
A* a = new Derived();
if(typeid(&A::reset)==typeid(&Derived::reset))// no override
{ *a = Derived(); } // instead of calling a1->reset()
else { a->reset(); } // if there is override
The problem with the above is that only public member functions can be used.
class Base {
virtual void func1();
}
class Derived : Base {
void func1();
void func2();
}
vector<Base *> vec;
vec.push_back(new Base()), vec.push_back(new Derived());
What is the correct/clean way to call func2 without knowing which index corresponds to which class? Is there a convention to do such a thing? I also want to avoid using typeid.
In your case the objects are sliced, as mentioned in king_nak's answer, so there's no safe way to call func2().
But you can store pointers to Base instead of Base objects - in this case you can use dynamic_cast:
std::vector<Base*> vec;
vec.push_back(new Base());
vec.push_back(new Derived());
for (auto obj : vec)
{
Derived* d = dynamic_cast<Derived*>(obj);
if (d)
{
d->func2();
}
}
Some info on dynamic_cast: link
PS: Also, if you want to call function func2() on Base objects, I think it makes sense to add a stupid implementation to Base class and make the function virtual.
This function will take one of said pointers and call func2 if possible, and simply return false otherwise
bool CallFunc2(Base* Bae){
Derived* Der;
if (Der = dynamic_cast<Derived*>(Bae))
{Der->func2(); return true;}
else
return false;
}
This works on the principle that dynamic_cast returns a null pointer if the object being cast cannot be converted.
If you don't want to use RTTI at all (including dynamic_cast), you could simulate its behaviour like Qt does it with qgraphicsitem_cast
Outline:
class Base {
public:
enum { Type = 0 };
virtual int type() { return Type; }
};
class Derived : public Base {
public:
enum { Type = 1 };
int type() { return Type; }
};
template<typename T>
inline T myobject_cast(Base *b) {
if (b) {
// Requires C++11
if (int(std::remove_pointer<T>::type::Type) == b->type()) {
return static_cast<T>(b);
}
/* Pre C++11 (might be UB, but works on many compilers, OpenSource and Commercial)
if (int(static_cast<T>(0)->Type) == b->type()) {
return static_cast<T>(b);
}
*/
}
return NULL;
}
// use:
Base *b = new Base;
Base *d = new Derived;
Derived *o1 = myobject_cast<Derived*> (b); // NULL
Derived *o2 = myobject_cast<Derived*> (d); // d
Each class would require a unique Type member for this to work.
Be aware that this will not work with "intermediate" classes in the hierarchy. Only the actual, most derived type will can be cast to (e.g. a DerivedDerived cannot be cast to a Derived, or Base for that matter).
You might also find an overload for const handy:
template<typename T> inline T myobject_cast(const Base *b)
{ return (b && int(static_cast<T>(0)->Type) == b->type()) ? static_cast<T>(p) : 0; }
const Base *cb = new Derived;
const Derived *co = myobject_cast<const Derived *>(cb);
I have strange assertion error and I can not find what is wrong with this code.
Assertion expression is _BLOCK_TYPE_IS_VALID(pHead->nBlockUse).
I simplified code a bit for better readability.
class Creator
{
public:
virtual ~Creator()
{
for (MyObject* item : _list)
{
delete item; <-- assertion error here
item = 0;
}
_list.clear();
}
template <class T>
T& create()
{
T * item = new T();
_list.push_back(item);
return *item;
}
private:
std::list<MyObject*> _list;
};
class A : public MyObject, public Creator
{
};
class B : public MyObject, public Creator
{
};
int main()
{
A a;
a.create<A>();
} <-- call of destructor
The idea is that an object witch inherits Creator, can create any other object, and hold pointers to those objects. While programmer can work with references. And when "super" object is destroyed, all "sub" objects are destroyed too.
Program works like a charm if I change to:
template <class T>
class Creator
{
public:
virtual ~Creator()
{
for (T* item : _list)
{
delete item;
item = 0;
}
_list.clear();
}
T& create()
{
T * item = new T();
_list.push_back(item);
return *item;
}
private:
std::list<T*> _list;
};
class A : public MyObject, public Creator<A>
{
};
class B : public MyObject, public Creator<B>
{
};
int main()
{
A a;
a.create();
}
Now create method creates only one type of object ( object A in this example ).
But I need, that create method could create any object that inherits MyObject. Like in first peace of code.
Any help for this assertion error would be appreciated. Thanks.
The issue is that your MyObject class lacks a virtual destructor, and you're attempting to call delete on a pointer to the derived class using a pointer to the base class MyObject. Issuing a delete on a derived object through a base class pointer is undefined behavior if the base class destructor is not virtual.
5.3.5 Delete (Paragraph 3)
In the first alternative (delete object), if the static type of the
operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined.
Once the destructor is made virtual in the base class MyClass, the following works correctly in Visual Studio 2013:
#include <list>
struct MyObject
{
virtual ~MyObject() {}
};
class Creator
{
public:
virtual ~Creator()
{
for (MyObject* item : _list)
{
delete item;
item = 0;
}
_list.clear();
}
template <class T>
T& create()
{
T * item = new T();
_list.push_back(item);
return *item;
}
private:
std::list<MyObject*> _list;
};
class A : public MyObject, public Creator
{
};
class B : public MyObject, public Creator
{
};
int main()
{
A a;
a.create<A>();
}
Problem is that you try to delete A object via MyObject pointer and MyObject destructor is not virtual. You could make MyObject's destructor virtual and then you can delete subclasses objects via pointer to MyObject. For more details on this issue see this question
I think the issue is with multiple inheritance. Here's a simplified way to reproduce the problem.
It can be fixed by
casting it to the most derived type OR
having the destructor of the base class be virtual.
In your case, the virtual function approach is best as it is recommended to have base class destructor(s) to be virtual to get the destruction calls through the inheritance hierarchy.
class A
{
};
class B
{
};
class C : public A, public B
{
};
int main()
{
// Fails with memory heap error
B* pB = new C();
delete pB;
}
To fix it
int main()
{
B* pB = new C();
// Casting it to the "full" type will fix it
C* pC = static_cast<C*>(pB);
delete pC;
}
The second program works because it is similar to this below.
int main()
{
// Pointer to the "full" type works
C* pC = new C();
delete pC;
}
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.
class Base
{
Base* next;
}
class Class1 : Base
{
}
Base* pBase = new Base();
Class1* pTest = new Class1();
pBase->next = pTest;
Class1* pClass1;
pClass1 = (Class1*)pBase->next;
I want to be able to write
pClass1 = pBase->next;
and get no compilation error C2440 (cannot convert). Or in other words I want pClass1 point to a class that pBase->next points to.
Is it possible with some operator overloading? How to do it?
template<class T>
class Base
{
T* next;
}
class Class1 : Base<Class1>
{
}
Class1* pTest1 = new Class1();
Class1* pTest2 = new Class1();
pTest1->next = pTest2;
Class1* pClass1;
pClass1 = pTest1->next;
If - at development time - you're sure that next points to an instance of Class1, make next a Class1 pointer instead of a Base pointer.
If you're not sure, and you only know it at compile time, you have to use a dynamic cast (possibly next will point to a Class2 instance later).
The closest I can get to what you are after is this:
class Class1;
class Base
{
public:
Base* next;
operator Class1*()
{
return (Class1*)this;
}
};
class Class1 : public Base
{
};
and:
Base* pBase = new Base();
Class1* pTest = new Class1();
pBase->next = pTest;
Class1* pClass1;
pClass1 = *pBase->next;
But this is really messing around with C++ in ways that you will pay for severely later. Just use one of the casts mentioned by Patrick.