3

Is the following code problamatic regarding inserting into a list an object that inherits from two classes?

class A
{
}

class B
{
}

class C : public A, public B
{

}

C *myObj = new C();
std::list<A*> myList;
myList.push_front(myObj);

Is creating a list of type A and inserting an object of type C which is part of type B problematic? I know this code compiles but I am affrade of memory issues. If its a problem, what other options do I have to solve this?

Shay
  • 633
  • 2
  • 11
  • 27

2 Answers2

3

As long as the list stores the data by reference or pointer and the destructor is virtual you're fine.

The basic problem is that you are not allowed to store a C into a variable of A, but you can store it into A& or A*. So A a = C() would be just as bad as storing a C into a list<A> or vector<A>. This would lead to slicing

Community
  • 1
  • 1
Voo
  • 29,040
  • 11
  • 82
  • 156
  • The list stores a pointer to C. Is that ok? At the end I pass the list to a function which expects a list of type *A Why there will be a problem if it was a vector and not a list? – Shay Dec 05 '12 at 18:27
  • @Shay `vector` vs `list` is irrelevant, what he means is if you store values, instead of pointers, slicing will occur. Also, deleting an object via the base class destructor, if that destructor is not `virtual` is undefined behavior, regardless of whether the destructor is trivial or not. So `A` needs to have a `virtual` destructor, and probably `B` as well. – Praetorian Dec 05 '12 at 18:28
  • I think I understood - there wont be a problem because the list only allocates the address. And if the function which receives the list only calles A functions, there wont be a problem, right? – Shay Dec 05 '12 at 18:30
  • @Shay That is correct, and the function could also downcast the object to a `C*` type and call functions of class C. You can use `dynamic_cast` to test whether the cast was successful. And I meant to say *deleting an object via a base class pointer ...* in my last comment. – Praetorian Dec 05 '12 at 18:33
0

Technically, as long as you add references or pointers of the objects to the list in order to avoid slicing and have virtual destructors you should be safe.

You could think of A and B as being interfaces to the polymorphic type. Take a look at this example:

class Drawable
{
    public:
        virtual ~Drawable() { }
        virtual void draw();
};

class Circle : public Drawable
{
    public:
        void draw() { std::cout << "Drawing a circle\n"; }
}

class Square : public Drawable
{
    public:
        void draw() { std::cout << "Drawing a square\n"; }
}

int main()
{
    std::list<Drawable*> shapeList { new Square(), new Circle(), new Square() };
}
Mihai Bişog
  • 998
  • 9
  • 24