views:

164

answers:

2

I'm trying to access the object (called a Vector) pointed to by a pointer held in a vector container, but I can't seem to get to it.

Here are the important code snippets:

int main{
    Vector<double>* test = new Vector<double>(randvec<double>());

    test->save();

    cout << Element::vectors[0];
return 0;
}

Where Vector is a template class, randvec<T>() returns a reference to a vector, save() is

template <class T>
void Vector<T>::save()
{
    vectors.push_back(this);
}

and vectors is static std::vector<Element*> vectors; defined in Element.h, the base class of Vectors.

Am I going about this all wrong? I'm trying to contain all the elements of a derived class in a static data member of the base class by using a vector of pointers to the main class.

My output from main() might tell you what's going on – I get the pointer 0x1001000a0. However, if I try to dereference that pointer, I get the following error:

error: no match for 'operator<<' in 'std::cout << * Element::vectors. 
std::vector<_Tp, _Alloc>::operator[] [with _Tp = Element*, _Alloc = std::allocator<Element*>](0ul)'

Why can't I dereference this pointer?

+2  A: 

The problem is not with dereferencing. The problem is that "<<" operator is not defined for Element::vectors

Pardeep
+1  A: 

It looks like you're missing an operator<< overload that can be used to output an Element. Note that it won't work if you just define the overload for Vector<T> because dereferencing Element::vectors[0] gives you an object of type Element.

Here's an (untested, sorry) example of how you can go about allowing derived classes (like Vector<T>) to override the stream-insertion behaviour of Element:

Add a virtual member function to Element:

class Element
{
   // other stuff

   virtual void write_to_stream(std::ostream& stream) const = 0;
};

Overload operator<< for Element to call this function:

std::ostream& operator<<(std::ostream& stream, const Element& element)
{
    element.write_to_stream(stream);  // dynamic dispatch as we call through reference
    return stream;
}

Then override the virtual member function in the derived classes to control how they should be written:

template<class T>
class Vector : public Element
{
   // other stuff
   virtual void write_to_stream(std::ostream& stream) const
   {
      // whatever you like goes here
   }
};
Mike Dinsdale
Wait, why wouldn't dereferencing twice give me an object of type Vector<T>?I've defined an output operator for Vector<T>, and that's the operator I'm trying to use. How do I interact with that version – do I have to cast the pointer?
Nick Sweet
The static type of `*Element::vectors[0]` is `Element` (because `Element::vectors[0]` is an `Element*`), even though the dynamic type of the object it points to is indeed `Vector<T>` (you're right that I probably shouldn't say it's an "object of type `Element`"!) One way to get the ability to overload the `operator<<` in `Vector<T>` is to delegate to a virtual function - I'll add an example to my answer.
Mike Dinsdale
...where by "it points to" I mean "`Element::vectors[0]` points to"...
Mike Dinsdale
@Mike Dinsdale: In the original question the dereference operator is not present: `cout << Element::vectors[0];` so the static type is *pointer to* ... At least from the code. Then again I don't use that compiler so I am not used to the error messages, and the error message might be actually saying that while copying the question to SO the star fell off.
David Rodríguez - dribeas
@David Rodriguez: I think the code he's actually showing is what he's describing when he says "My output from main() might tell you what's going on – I get the pointer 0x1001000a0". Then he says "However, if I try to dereference that pointer..." which I interpreted to mean he added the `*` to the code (which would then make sense out of the `*` in the error message). But I could have misunderstood, I had to read it a few times before hitting on this interpretation!
Mike Dinsdale