2

I'm really confused, so I have to ask this. I try to write an application, but I don't know how to reach the variables of the derived class, which are in a vector in the Base class. The code is:

class A {
public:
    A() { };

    std::vector<A> aVector;

    void Foo();
}

class B : public A {
public:
    B() { };

    int j;
}

void A::Foo() {
    aVector.push_back( B() );

    // Here I would like to reach B::j, but only the members and variables of A comes in
    aVector[0].j; // wrong
    B b = aVector[0];   // no suitable user-defined conversion from "A" to "B" exists
                        // should I use cast? which one?
}

I'm currently learning inheritance and this kind of things through application programming, and now I'm really stuck.

I looked for other questions, but could not find any that solves my problem. If there is, and I missed, then sorry.

David G
  • 94,763
  • 41
  • 167
  • 253
matthew3r
  • 682
  • 4
  • 9
  • 26

4 Answers4

2

You need to store pointers to A so that your new B object won't get "sliced" (see explanation here) when pushed into the vector.

Also, when you want to use specifically a child method / variable on a pointer from the base class, you need to cast it into the proper type

std::vector<A*> aVector;
aVector.push_back(new B());
B* b = (B*)aVector[0];
cout << b->j;
// remember to delete the content of aVector

Casting an object like this can be dangerous if you are not 100% sure that it is of the type you're casting it in.

See this thread for more information on casting (C style, dynamic_cast and static_cast)

Community
  • 1
  • 1
emartel
  • 7,712
  • 1
  • 30
  • 58
  • Ideally you'd store *smart* pointers to `A`. Imagine a naked vector with millions of pointers in it, and suddenly an exception occurs. :P – cHao Nov 26 '12 at 17:17
  • While I agree, I think we're moving away from the initial question :) – emartel Nov 26 '12 at 17:19
  • Thank you! I accepted this, because that gave me a working solution. But now I see that there is still many to learn :) – matthew3r Nov 26 '12 at 17:28
1

Since the vector is declared to hold objects of type A, when you push a B in to the vector, all the B-ness is stripped away from the object that's stored in the vector. This is known as the slicing problem.

When you later try to access the B elements of the objects stored in the vector you can't because they simply don't exist. You don't have a vector of B objects -- you have a vector of A objects.

In order to solve this problem, you need to store A objects not by value, but by reference or by pointer. You can't store references in a vector, so this leaves you with pointers.

Community
  • 1
  • 1
John Dibling
  • 99,718
  • 31
  • 186
  • 324
0

This has nothing to with vectors. If B derives from A then the following code:

A a;
B b = a;

is an error (unless there is some method to convert).

This is correct - your vector items you should be able to handle uniformly. If this means the code that uses the vector expects all items to be B then just make a vector<B>. If not, then you have no business converting an A to a B anyway.

djechlin
  • 59,258
  • 35
  • 162
  • 290
0

You should never try to access derived class members from the base class. The base class should be agnostic about the implementation details of the derived class. What you are doing is not polymorphic. In other words your B instances cannot act like A instances, because you provided no virtual methods and overrode no virtual methods.

The entire design and approach is incorrect. A::Foo() should be a virtual method (Perhaps even abstract). And you should be doing the work in B::Foo().

And another thing, you shouldn't hold a vector of just plain old A. It should be pointers to A. So std::Vector. And that member should be prefixed with the letter m, to indicate it's a member variable of the class. So std::vector mSomething;

C.J.
  • 15,637
  • 9
  • 61
  • 77