I have an abstract class Base and derived class Derived:
class Base
{
public:
Base(int n) :_n(n) { _arr = new int[n]; }
virtual ~Base() { delete[] _arr; }
Base(Base&& other) { _n = other._n; _arr = other._arr; other._arr = nullptr; other._n = 0; }
virtual void func() = 0;
private:
int _n;
int* _arr;
};
class Derived : public Base
{
public:
Derived(int m, int n) : Base(n), _m(m) { _arr = new int[m]; }
~Derived() { delete[] _arr; }
Derived(Derived&& other) : Base(std::move(other)) { _m = other._m; _arr = other._arr; other._arr = nullptr; other._m = 0; }
void func() override { cout << "func"; }
private:
int _m;
int* _arr;
};
Then I have a class Bag which contains a rvalue reference of Base:
class Bag
{
public:
Bag(Base&& b) : _b(std::move(b)) {}
void func() { _b.func(); }
private:
Base&& _b;
};
int main()
{
Bag bag(Derived(1, 1));
bag.func();
}
I use a rvalue reference member _b because I just want to take a temporary object in Bag's constructor. However, after bag.func() I got an error: abort() is called. It seems that bag._b's type changes from Derived to Base after the temporary object Derived(1,1) is destructed.
bag.func() works after I delete virtual ~Base() { delete[] _arr; }. Why? If I need Base's destructor, how can I change my code?
Base&& _b is a reference to the temporary object, when that temporary is destroyed at the end of the line Bag bag(Derived(1, 1)); the reference becomes a dangling reference and any use of the reference is undefined behaviour.
You could change _b to a value instead but that would slice your object.
If you want to store a polymorphic object the only real option is to use a pointer (ideally a smart one). For example:
class Bag
{
public:
Bag(std::unique_ptr<Base>&& b) : _b(std::move(b)) {}
void func() { _b->func(); }
private:
std::unique_ptr<Base> _b;
};
int main()
{
Bag bag(std::make_unique<Derived>(1, 1));
bag.func();
}
Note that you should also ensure that Base and Derived follow the rule of five otherwise you may encounter issues when you assign objects.
Related
casting shared pointer from B class to A class is not working the console output isn't 12 it's (it outputs A's x but i want B's x)(probably an other memory address). what's wrong with my code
#include <iostream>
#include <memory>
class A
{
public:
int x;
};
class B : public A
{
public:
B(){}
B(const B*){}
int x = 12;
};
std::shared_ptr<A> create()
{
return std::make_shared<B>(new B);
}
int main(){
std::shared_ptr<A> p;
p = create();
std::cout << p->x << std::endl;
std::cin.get();
return 0;
}
A::x and B::x are different objects. Variable access is never polymorphic in C++, so when you access p->x, you're accessing A::x. A::x was never initialized though, so the behavior of your program is undefined.
You need to either have your derived class's constructor initialize the base class's object or delegate that responsibility to the base class's constructor:
class A
{
public:
A(int x) : x{x} {}
int x;
};
class B : public A
{
public:
B() : A{12} {}
};
Live Demo
Alternatively you could wrap x in a virtual accessor method:
class A
{
public:
virtual ~A() = default;
virtual int x() const = 0;
};
class B
{
public:
int x() const override
{
return x_;
}
private:
int x_ = 12;
};
Live Demo
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 stumbled upon casting sideways from derived to derived class and discovered a gap in my knowledge. I had been living in a world where this is possible - until now. Instead, std::bad_cast is thrown. What's going on here?
#include <iostream>
class Base
{
protected:
int x_;
public:
Base(int x) : x_(x) {}
virtual ~Base() = default;
int x() const { return x_; }
virtual void setX(int x) = 0;
};
class Editable : public Base // class implements setters
{
public:
Editable(int x) : Base(x) {}
void setX(int x) { x_ = x; }
};
class ReadOnly : public Base // class implements empty setters
{
public:
ReadOnly(int x) : Base(x) {}
void setX(int x) {}
};
int main()
{
Editable editable(4);
ReadOnly &readOnly = dynamic_cast<ReadOnly&>(editable); // std::bad_cast
}
This is what is meant when people say that dynamic_cast can cast sideways:
struct A { virtual ~A() = default; };
struct B { virtual ~B() = default; };
struct D : A, B {};
B* pb = new D();
A* pa = dynamic_cast<A*>(pb); // OK
i.e., it allows you to cast a B* to a A* if the pointer is pointing to something that's derived from both A and B. For the cast to succeed, there still must be an A subobject for the pointer to point to (or the reference to bind to, if you are casting to a reference type).
In your case, e is an Editable. There's no ReadOnly subobject anywhere in there. So the cast fails.
You're not casting sideways.
You're casting from one derived of a base to another.
Let's hypothetically say your cast succeeded, and there's a public int member called readOnlyInt in ReadOnly class.
How can the compiler perform readonly.readOnlyInt?
There's no readOnlyInt in the casted ReadOnly & cause it is in fact an Editable.
Casting sideways involves multiple inheritance structures & looks something like this:
class A {
virtual ~A() {}
};
class B {
virtual ~B() {}
};
class C : public A, public B {
};
int main() {
B *b = new C();
A *a = dymanic_cast<A *>(b);
return 0;
}
I have a class which uses a class of base pointers to derived objects, so I need to have my own desructor for deleting the vector's elements and custom copy and assignment funcitons. I'm not entirely sure about the preferred way of implementing a structure like below and writing the right copy and assignment constructors and destructors for it. May I ask you to guide me? I've read a lot and searched but I'm still not sure.
class Base
{
public:
Base();
~virtual Base();
int a;
int type; // Derived1 or Derived2
std::string b;
...
}
class Derived1 : public Base
{
public:
Derived1();
Derived1(const Base* a);
virtual ~Derived1();
}
class Derived1
{
Derived1::Derived1(const Base *a) : Base(a)
{
}
}
class Derived2 : public Base
{
public:
Derived2();
Derived2(const Base* a);
virtual ~Derived2();
std::string d1;
std::string d2;
int d3;
}
class Derived2
{
Derived2::Derived2(const Base *a) : Base(a) {
this->d1 = ((Derived2*)a)->d1;
this->d2 = ((Derived2*)a)->d2;
this->d3 = ((Derived2*)a)->d3;
}
}
class A
{
public:
A();
~A();
A(const A& a);
A& operator = (const A& a);
std::string someString;
std::vector<Base*> vect;
}
A::~A() {
std::vector<Base*>::iterator it = vect.begin();
while (it != vect.end()) {
delete (*it);
it++;
}
A::A(const A &a)
{
someString = a.someString;
for(std::size_t i = 0; i < a.vect.size(); ++i {
someString = a.someString;
Base* base = a.vect.at(i);
if(base->type == base::TypeD1) {
base = new Derived1( a.vect.at(i) );
vect.push_back( base );
}
else {
base = new Derived2( a.vect.at(i) );
vect.push_back( base );
}
}
}
Your loop in the destructor is fine in practice, and is the
usual solution. Formally, it is undefined behavior, since you
are leaving objects in the vector (pointers to deleted objects)
which aren't copiable, but in practice: the vector won't copy
them unless you resize it to something bigger, or insert or
erase on it. If you really want to avoid the undefined
behavior:
for ( auto current = vect.begin(); current != vect.end(); ++ current ) {
Base* tmp = *it;
*it = nullptr;
delete tmp;
}
But this is one case where I probably wouldn't bother (and
I tend to be more sensitive to undefined behavior than most).
First, do you actually need to copy and assign objects of type A? If no, the simple solution is:
class A
{
public:
A();
~A();
A(const A&) = delete;
A(A&&) = default;
A& operator=(const A&) = delete;
A& operator=(A&&) = default;
// ...
};
If yes, then you want some polymorphic way of copying the elements of the vector. (Any time at all you have if (b->type == Base::TypeD1) { do_this(); } else { do_that(); }, stop and think if it would make sense to add a virtual function for do_this/do_that. The else-if-heimer's way doesn't allow for future new derived classes; the virtual way does.)
class Base
{
public:
// ...
virtual Base* clone() const = 0;
// ...
};
class Derived1 : public Base
{
public:
virtual Derived1* clone() const;
};
Derived1* Derived1::clone() const {
return new Derived1(*this);
}
The copy assignment operator of A will need to destroy the old contents of the lhs, just like the destructor, and then copy the new contents over, just like the copy constructor. So let's put those two operations in private functions:
class A
{
public:
A();
~A();
A(const A&);
A(A&&) = default;
A& operator=(const A&);
A& operator=(A&&) = default;
// ...
private:
void destroy_contents();
void copy_from(const std::vector<Base*>& v);
};
void A::destroy_contents() {
std::vector<Base*>::iterator it = vect.begin();
while (it != vect.end()) {
delete (*it);
++it;
}
vect.clear();
}
void A::copy_from(const std::vector<Base*>& v) {
std::vector<Base*>::const_iterator it = v.begin();
while (it != v.end()) {
vect.push_back((*v)->clone());
++it;
}
}
A::~A() { destroy_contents(); }
A::A(const A& a) :
someString(a.someString),
vect()
{
copy_from(a.vect);
}
A& A::operator=(const A& a) {
if (this != &a) {
someString = a.someString;
destroy_contents();
copy_from(a.vect);
}
return *this;
}
If you have a vector of any pointer type, the vector does not know anything about the type behind the pointer, nor does it care: The vector operates on the pointers only, copying them to a new location if need be, but never even touching the objects themselves. As such, it is your responsibility to destroy the objects themselves.
As James Kanze points out, there is a slight danger of undefined behavior when handling invalidated pointers. However, since the vector is not used in any way after deleting the objects it holds, no undefined behavior is invoked in the code you've given (the vector won't need to reallocate its memory so it won't need to assign invalidated pointers, and destruction of pointers is a noop). As such, your destructor of class A is perfectly fine.
The copy constructor of class A, however, is unnecessarily complicated and an ample source of errors (it needs to be updated whenever a new derived class is defined!). The best way to do this is to use a clone() function:
class Base {
public:
//...
virtual Base* clone() const = 0; //Returns a new copy of the object. Pure virtual if the Base class is abstract.
};
class Derived1 : public Base {
public:
Derived1(const Derived& a);
virtual Derived* clone() const {
return new Derived1(*this);
}
};
If you make clone() pure virtual in the base class, you have the guarantee that your compiler will complain if you forget to implement it in any derived class. With that, the copy constructor of class A is next to trivial:
A::A(const A &a) {
someString = a.someString;
for(std::size_t i = 0; i < a.vect.size(); ++i {
vect.push_back(a.vect[i]->clone());
}
}
So I'm having a little bit of problems understanding how I should fix this polymorphic issue I've ran into. To make things short, let's define only two levels of classes, a father and two sons:
The parent:
class Entity {
public:
int x;
Entity();
~Entity();
Entity(const Entity&);
Entity &operator=(const Entity&);
};
The two sons:
class EntitySon1 : public Entity {
public:
int b;
EntitySon1();
~EntitySon1();
EntitySon1(const EntitySon1&);
EntitySon1 &operator=(const EntitySon1&);
};
class EntitySon2 : public Entity {
public:
int a;
EntitySon2();
~EntitySon2();
EntitySon2(const EntitySon2&);
EntitySon2 &operator=(const EntitySon2&);
};
Please, forget the fact that in this example all classes only have an int value and the standard operator= should therefore be enough, in the real project these classes are more complex so I do have the need to implement one myself and they are succesfully calling parent ones as well.
So now, somewhere in my project, I have an array of Entity*, which can only be either son1 or son2. I want to go through this array of entities and make copies into another array. The code I'd like to be able to write is something like:
for (i = 0; i < entities; ++i) {
entityCopiesArray[i] = entitiesArray[i];
}
Problem is, both entityCopiesArray and entitiesArray are of type (Entity*) so when the assign is done, only Entity.operator=() gets called, while I need, in the case that current Entity is son1, have both Entity.operator=() and EntitySon1.operator=() called.
I know I can cast each variable on the array so the right operator gets called, but that needs extra information to tell which entities are son1, which are son2, and also need to be typed manually for every possible Entity's son.
Is there any other way around this, or am I stuck with doing:
if (isSon1())
(EntitySon1)entityCopiesArray[i] = (EntitySon1)entitiesArray[i];
else if (isSon2())
(EntitySon2)entityCopiesArray[i] = (EntitySon2)entitiesArray[i];
// ... etc
edit: I made this post late night and tried to compact the information as much as possible so I said things that weren't accurate. I obviously have an array to Entity*, else I wouldn't be able to use polymorphism.
Consider the following:
struct Base {
int a;
};
struct Derived1 : public Base {
int d1Data[100];
};
struct Derived2 : public Base {
char d2Data[1500];
};
Now if we do the following:
Entity* e = new Entity;
Derived1* d1 = new Derived1;
Derived2* d2 = new Derived2;
std::cout << sizeof(*e) << ", " << sizeof(*d1) << ", " << sizeof(*d2) << '\n';
What will the output be? Hint: The numbers are not going to be the same.
So now what happens in each of the following cases?
*e = *(Entity*)d1;
*(Derived1*)e = *d1;
*(Derived2*)d1 = *d2;
*(Entity*)d1 = *(Entity*)(d2);
*(Derived1*)d2 = *d1;
None of these cases is particularly good. Your post makes it sound like you are setting yourself up for a bad case of object slicing.
DO NOT DO.
On the other hand, if what you are looking to do is to clone objects from a list:
std::vector<Base*> entities;
std::vector<Base*> copies;
entities.push_back(new Derived1);
entities.push_Back(new Derived2);
for (size_t i = 0; i < entities.size(); ++i) {
Base* clone = make_a_copy_of(entities[i]);
}
then the way to do this is to add a member function to Base.
struct Base {
int a;
virtual Base* clone() const = 0;
};
struct Derived1 : public Base {
int d1Data[100];
Base* clone() const override {
return new Derived1(*this);
}
};
struct Derived2 : public Base {
char d2Data[1500];
Base* clone() const override {
return new Derived2(*this);
}
};
int main() {
std::vector<Base*> entities;
std::vector<Base*> copies;
entities.push_back(new Derived1);
entities.push_Back(new Derived2);
for (size_t i = 0; i < entities.size(); ++i) {
Base* clone = entities[i]->clone();
}
// remember to delete all the objects we allocated,
// or wrap them with std::unique_ptr
return 0;
}
I will probably be scowled at for using raw pointers like this without using something like std::unique_ptr to ensure the objects have a lifetime, so here is a complete version using unique_ptr. I'm not using make_unique because neither my GCC (4.8.2) or MSVC appear to support it.
#include <iostream>
#include <vector>
#include <memory>
struct Base {
int m_a;
Base(int a) : m_a(a) {}
virtual ~Base() { std::cout << "Dtoring " << m_a << '\n'; }
virtual std::unique_ptr<Base> clone() const = 0;
};
struct Derived1 : public Base {
int d1Data[100];
Derived1(int a) : Base(a) {}
virtual ~Derived1() { std::cout << "D1 at " << (void*)this << " dtord\n"; }
std::unique_ptr<Base> clone() const override { return std::unique_ptr<Derived1>(new Derived1 (*this)); }
};
struct Derived2 : public Base {
char d2Data[10000];
Derived2(int a) : Base(a) {}
virtual ~Derived2() { std::cout << "D1 at " << (void*)this << " dtord\n"; }
std::unique_ptr<Base> clone() const override { return std::unique_ptr<Derived2>(new Derived2 (*this)); }
};
int main()
{
std::vector<std::unique_ptr<Base>> entities;
{
std::vector<std::unique_ptr<Base>> copies;
entities.emplace_back(new Derived1 (3));
entities.emplace_back(new Derived2 (5));
for (auto& ent : entities) {
copies.emplace_back(ent->clone());
}
std::cout << "copies going out of scope\n";
}
std::cout << "entities going out of scope\n";
return 0;
}
Live demo: http://ideone.com/lrgJun
---- EDIT ----
When you inherit a class, you also inherit it's data members into your overall structure. In this example, the effective structure of Derived1 is:
struct Derived1 {
int a; // from Base
int d1Data[100];
};
My implementation of clone is quietly relying on the copy constructor which is essentially doing a memory copy of src to dest, the equivalent of memcpy(this, src, sizeof(*this));. Because of this you don't need to chain calls to clone or anything like that, the magic is done in the copy constructor.
If you need to add instances of Base into your mix, we can implement the clone member in Base - but bear in mind that any "special" members you add to Base are going to be inherited in all the derived classes too.
I'll convolute the classes a little and show you what the copy constructors for Base and Derived1 effectively look like:
struct Base {
int m_int;
double m_double;
std::string m_name;
private:
unsigned int m_baseOnly;
...
};
struct Derived1 : public Base {
// inherited m_int, m_double and m_name
// also inherited m_baseOnly, we just can't access it.
std::array<int, 100> m_data;
std::string m_title;
std::shared_ptr<Base> m_buddy;
...
};
At this point, the actual in-memory structure of a Derived1 looks like this:
Derived1 {
int m_int;
double m_double;
std::string m_name;
unsigned int m_baseOnly;
std::array<int, 100> m_data;
std::string m_title;
std::shared_ptr<Base> m_buddy;
};
Given these definitions, unless we implement our own copy constructor or disable copy construction, this is effectively what the compiler will generate for us:
Base::Base(const Base& rhs) // Base copy constructor
: m_int(rhs.m_int)
, m_double(rhs.m_double)
, m_name(rhs.m_name)
, m_baseOnly(rhs.m_baseOnly)
{
}
Derived1::Derived1(const Derived1& rhs)
: Base(rhs) // copy-construct the Base portion
, m_data(rhs.m_data) // hence why I used std::array
, m_title(rhs.m_title)
, m_buddy(rhs.m_buddy)
{
}
My implementation of clone for Derived1
std::unique_ptr<Base> clone() const override
{
return std::unique_ptr<Derived1>(new Derived1 (*this));
}
or
std::unique_ptr<Base> clone() const override
{
const Derived1& rhs = *this; // Reference to current object.
Derived1* newClone = new Derived1(rhs);
return std::unique_ptr<Derived1>(newClone);
}
which is creating a new Derived1, invoking the new, empty, clone's copy-ctor with the current object as rhs and filling out the clone.
I have an array of Entities, which can only be either son1 or son2.
In general this is not possible. But you can have an array of Entity*, each of which points to a Son1 or a Son2. Then you can have a virtual clone function such that a member of this family creates a copy of itself and returns a pointer (of type Entity*) to it. Then you can copy the array quite easily.