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;
}
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;
}
i am new to shared pointers. I would like to have a method which returns reference to an object. The object will be created inside a method by make_shared and also stored in a vector as a shared pointer of base class. I guess my code is not the best way to do it. Any suggestions?
Thank you.
class A {
public:
};
class B : public A {
public:
};
class Factory {
public:
B& createA() {
std::shared_ptr<B> b = std::make_shared<B>();
container.push_back(b);
return *b;
}
private:
std::vector<std::shared_ptr<A>> container;
};
int main() {
Factory factory;
B& b = factory.createA();
// work with B here...
}
Say I have a class:
class Foo{
public:
Foo(){
}
//Is it possible to create a function like this:
virtual Foo* createOb(){
//Should create a new Foo,Bar or Fiz, depending on the actual object type.
}
}
class Bar: public Foo{
public:
Bar(){
}
}
class Fiz: public Foo{
public:
Fiz(){
}
}
Is it possible to have a method createOb() in the base class, so when createOb() is called on an instance of one of the derived classes, that an instance of the derived class is created ?
Yes, it can be done, using CRTP.
Bu first, returning a raw pointer obtained from new is very dangerous. In c++ raw pointers should be used only when they do not have ownership of the pointed object. So I took the liberty to use unique_ptr:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base>
{
return std::unique_ptr<Base>{};
}
};
// abstract works too:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base> = 0;
};
template <class Derived>
struct Base_crtp : Base {
auto create_obj() -> std::unique_ptr<Base> override /* final */
{
return std::unique_ptr<Base>{new Derived{}};
}
};
struct D1 : Base_crtp<D1>
{
};
struct D2 : Base_crtp<D2>
{
};
And then:
auto b1 = std::unique_ptr<Base>{new D1{}};
auto b2 = std::unique_ptr<Base>{new D2{}};
auto new_d1 = b1->create_obj();
auto new_d2 = b2->create_obj();
Definitely YES!!!
When a method is declared virtual in base class, and called through the derived class object, then the derived class function gets called (Read vprt, vtable concept in c++).
#include <iostream>
using namespace std;
class A{
public:
virtual A* getobj(){
return new A();
}
};
class B: public A{
public:
B(){cout<<"B constructor"<<endl;}
virtual A* getobj(){
return new B();
}
};
int main()
{
A *a = new B();
A *second = a->getobj();
return 0;
}
In the above code, we are calling the getobj() function using class B's object.
Here the constructor of class B is called twice.
first, for new B() in main
secondly for getobj function call which again creates object of B
This is not an optimal solution, but it works.
In your .h
class Foo{
public:
Foo();
virtual Foo* createOb();
};
class Bar: public Foo{
public:
Bar();
};
class Fiz: public Foo{
public:
Fiz();
};
In your .cpp
#include "Header.h"
Foo::Foo() {}
Foo* Foo::createOb(){
if (dynamic_cast<Bar*>(this)) {
return new Bar();
}
else if (dynamic_cast<Foo*>(this)) {
return new Foo();
}
return nullptr;
}
Bar::Bar() {}
Fiz::Fiz() {}
As already suggested please consider a pure virtual method
No, this is not possible with "pure" inheritance. The classes must override createOb() member function in order to support cloning.
You can see why this is not possible by considering separate compilation of classes. An implementation of one-fits-all createOb() member function must be completed in isolation from Bar and Fiz, making it impossible for the base to know the type of its subclasses.
An implementation with a pure virtual function in the base is very common, though.
Another approach is to use Curiously Recurring Template Pattern (CRTP) to implement cloning. This article explains how it can be done.
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;
}
when reading "Beyond the C++ Standard Library: An Introduction to Boost " ,I got a very interesting example:
class A
{
public:
virtual void sing()=0;
protected:
virtual ~A() {};
};
class B : public A
{
public:
virtual void sing( )
{
std::cout << "Do re mi fa so la"<<std::endl;;
}
};
and I do some testing:
int main()
{
//1
std::auto_ptr<A> a(new B); //will not compile ,error: ‘virtual A::~A()’ is protected
//2
A *pa = new B;
delete pa; //will not compile ,error: ‘virtual A::~A()’ is protected
delete (dynamic_cast<B*>(pa)); //ok
//3
boost::shared_ptr<A> a(new B);//ok
}
what I am very curious here is how ~shared_ptr works?
how it deduce the derived class B ?
Thanks advance for your help!
thanks all,
I write a simple sample about how ~shared_ptr works
class sp_counted_base
{
public:
virtual ~sp_counted_base(){}
};
template<typename T>
class sp_counted_base_impl : public sp_counted_base
{
public:
sp_counted_base_impl(T *t):t_(t){}
~sp_counted_base_impl(){delete t_;}
private:
T *t_;
};
class shared_count
{
public:
static int count_;
template<typename T>
shared_count(T *t):
t_(new sp_counted_base_impl<T>(t))
{
count_ ++;
}
void release()
{
--count_;
if(0 == count_) delete t_;
}
~shared_count()
{
release();
}
private:
sp_counted_base *t_;
};
int shared_count::count_(0);
template<typename T>
class myautoptr
{
public:
template<typename Y>
myautoptr(Y* y):sc_(y),t_(y){}
~myautoptr(){ sc_.release();}
private:
shared_count sc_;
T *t_;
};
int main()
{
myautoptr<A> a(new B);
}
the key is:
template construct function
the resource not deleted in ~shared_ptr ,it is deleted by shared_count
Surprisingly, the key here is not boost::shared_ptr destructor but its constructor(s).
If you look into boost/shared_ptr.hpp, you will see that shared_ptr<T> does not 'simply' have a constructor expecting a T * but :
template<class Y>
explicit shared_ptr( Y * p );
In //3 when you construct a boost::shared_ptr from a B *, no conversion to A * takes place, and the shared_ptr internals are built with the actual B type. Upon destruction of the object, deletion occurs on a B pointer (not through a base class pointer).
The shared_ptr class template has a member of class type shared_count, which in turn has a member of type pointer to class sp_counted_base. The constructor template for class shared_count assigns a pointer to an instance of the class template sp_counted_impl_p to this member which is templated by the type of the constructor argument, not by the shared_ptr::value_type. sp_counted_base has a pure virtual member function dispose which is overwritten by sp_counted_impl_p. Because sp_counted_impl_p knows the type B in your example, it can delete it without access to the base class destructor, and because it uses virtual dispatch, the type is determined at runtime. This method requires a combination of parametric and subtype polymorphism.