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.
Related
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.
I have class A which has struct as member and another class B which inherit class A and class B's struct inherit class A's struct.
class A
{
public:
struct st
{
int x;
int y;
};
};
class B : public A
{
public:
struct st : A::st
{
int z;
};
};
following code give me error: what is the way to do this thing
B::st* obj = NULL;
obj = new A::st [10];
What you are trying is wrong since B::st is sub-type of A::st. Hence, a pointer to A::st cannot be automatically converted to a pointer of type B::st.
For the same reason, you can't use:
B* bPtr = new A;
You can do the other way around.
A::st* obj = NULL;
obj = new B::st; // Don't use the array new. That is going to be problematic.
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;
}
I am trying to use a smart pointer class in the following way
class A
{
friend class B;
virtual methods ();
protected:
virtual ~classA();
}
class B:public QSharedPointer<class A>
{
class B();
~ class B();
}
I plan to replace occurrences of Class A* with class B. Is this approach correct?
No this is not really the way to do this. It looks like your design goal here is to make it impossible for someone to allocate an object of type A without putting it in a smart pointer. The normal way to do this is not to inherit from the smart pointer, but to make your type have
A private constructor
A private destructor
A public static factory method returning in this case QSharedPointer
A private deleter class that is a friend of class A
Here is an example using boost::shared_ptr (I do not have a QT installation right now, but you should be able to just replace all instances of boost::shared_ptr with QSharedPointer)
#include <boost/shared_ptr.hpp>
class A {
private:
A() {}
~A() {}
struct deleter {
void operator()(A* val) {delete val;}
};
friend class deleter;
public:
static boost::shared_ptr<A> create() {
return boost::shared_ptr<A>(new A(), A::deleter());
}
};
int main()
{
//A a1; //compile error
//A *a2 = new A(); //compile error
boost::shared_ptr<A> a3 = A::create();
return 0;
}
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();
}