How to use the iterator from base class in a derived class?

W

wangxiaohu

I am trying to write a class myVector based on std::vector and add
only a sort method. The sort method needs to access the array stored
in the base class using iterator. I have following draft code. However
it never compile. Can anyone take a look and tell me how to fix it?
Thanks!

#include <vector>
#include <iostream>

using namespace std;

template <typename T> class myVector : public vector<T>
{
public:
void Sort();
};

template <typename T> void Sort<T>::Sort()
{
if (this.size() < 2)
{
return;
}

vector<T>::iterator i;

for (i = this.begin(); i != this.end(); i++)
{
//rest part ignored....
}
}
 
G

Guest

I am trying to write a class myVector based on std::vector and add
only a sort method. The sort method needs to access the array stored
in the base class using iterator. I have following draft code. However
it never compile. Can anyone take a look and tell me how to fix it?
Thanks!

#include <vector>
#include <iostream>

using namespace std;

template <typename T> class myVector : public vector<T>

The general advice is to not inherit from the standard containers,
instead create a class that wraps the container.
{
public:
void Sort();
};

template <typename T> void Sort<T>::Sort()

template said:
{
if (this.size() < 2)

this->size()

This is a pointer to the current object, you need to use the dereference
operator (->) when accessing members of the current object.
 
K

Kai-Uwe Bux

wangxiaohu said:
I am trying to write a class myVector based on std::vector and add
only a sort method.

BadIdea(tm). That is abuse of inheritance. You should use a free standing
function instead:

template < typename T, typename A >
void sort_vector ( std::vector<T,A> & sequence ) {
std::sort( sequence.begin(), sequence.end() );
}

or maybe even more generic:

template < typename Container >
void sort_sequence ( Container & sequence ) {
std::sort( sequence.begin(), sequence.end() );
}

or with a concept check:

template < typename Container >
void sort_sequence
( Container & sequence,
typename enable_if
< is_sequence< Container >::value, void* >::type = 0 ) {
std::sort( sequence.begin(), sequence.end() );
}


There are some cases where public inheritance from std::vector<> is
justified. This does not look like one of them.

The sort method needs to access the array stored
in the base class using iterator. I have following draft code. However
it never compile. Can anyone take a look and tell me how to fix it?
Thanks!

#include <vector>
#include <iostream>

using namespace std;

Don't put using directives in header files. Your decision to pull all
identifiers from the standard namespace is inflicted upon every user of
your class. That is very intrusive.

template <typename T> class myVector : public vector<T>
{
public:
void Sort();
};

template <typename T> void Sort<T>::Sort()

Shouldn't that be something like

template <typename T>
void myVector::Sort()

{
if (this.size() < 2)
{
return;
}

vector<T>::iterator i;

You would need to say

typename std::vector<T>::iterator i;

The keyword here is "dependent name".

for (i = this.begin(); i != this.end(); i++)
{
//rest part ignored....
}
}

BTW: why are you doing your own sort algorithm? any why only for vectors? It
is _very_ hard to beat std::sort() from the header <algorithm>.


Best

Kai-Uwe Bux
 
W

wangxiaohu

I just want to see if I can add a Sort() method to the existing vector
container.

What you've shown is write a individual function, which does work for
the purpose, but does not answer my question.

But really thanks to your detailed example!

wxh
 
K

Kai-Uwe Bux

wangxiaohu said:
I just want to see if I can add a Sort() method to the existing vector
container.

What you've shown is write a individual function, which does work for
the purpose, but does not answer my question.

It appears you asked out of curiosity. Here is one way to do it:

template < typename T >
class sort_vector : public std::vector< T > {
public:

sort_vector ( void )
: std::vector< T > ()
{}

template < typename A >
sort_vector ( A a )
: std::vector< T > ( a )
{}

template < typename A, typename B >
sort_vector ( A a, B b )
: std::vector< T > ( a, b )
{}

template < typename A, typename B, typename C >
sort_vector ( A a, B b, C c )
: std::vector< T > ( a, b, c )
{}

template < typename A, typename B, typename C, typename D >
sort_vector ( A a, B b, C c, D d )
: std::vector< T > ( a, b, c, d )
{}

void sort ( void ) {
std::sort( this->begin(), this->end() );
}

}; // sort_vector<>


Note the templated constructors. They just forward everything to the
underlying vector. One of those even allows to convert from std::vector<T>
to sort_vector<T>. That mitigates one of the most troublesome drawbacks of
public inheritance from standard containers: surprises when used with
functions like

template < typename T, typename A >
std::vector<T,A> reverse_order ( std::vector<T,A> const & );

Note that sort_vector<T> will match the argument type. But the result will

and: please don't top post. It is frowned upon around these parts of the
net. See the FAQ for the sentiment about top-posting and other netiquette
matters that most regulars of this group share.


[snip]


Best

Kai-Uwe Bux
 
T

Tristan Wibberley

The general advice is to not inherit from the standard containers,
instead create a class that wraps the container.

I'd heard that was because somebody might use a reference to your object
with type std::vector<...>& and use all the wrong functions. What about
private inheritance?

Is there any other problem that makes that a bad idea too?

It would save the repetitive typing of all the overloads to forward to
the implementation if one could just type "using std::vector<...>
member;" over and over with different members.

--
Tristan Wibberley

Any opinion expressed is mine (or else I'm playing devils advocate for
the sake of a good argument). My employer had nothing to do with this
communication.
 
K

Kira Yamato

I'd heard that was because somebody might use a reference to your object
with type std::vector<...>& and use all the wrong functions.

This doesn't make sense. I thought the whole point of Object-Oriented
Programming is that polymophisms are encouraged as a coding structure.

If a derived class can potentially ``damaged'' the integrity of the
base class, then as the designer of the base class he shouldn't have
allowed his methods be declared virtual (so that the derived class
could not override it). If so, how then can any reference of the base
class be using any wrong methods supplied by the derived class?
Is there any other problem that makes that a bad idea too?

Yea, I like to know too.
 
I

Ian Collins

Tristan said:
I'd heard that was because somebody might use a reference to your object
with type std::vector<...>& and use all the wrong functions. What about
private inheritance?

Is there any other problem that makes that a bad idea too?
Standard containers don't have virtual destructors.
It would save the repetitive typing of all the overloads to forward to
the implementation if one could just type "using std::vector<...>
member;" over and over with different members.

Rather than extending a container, consider providing a function or
operator that operates on one. std::sort would have solved the OP's
problem.
 
T

Tristan Wibberley

... I thought the whole point of Object-Oriented
Programming is that polymophisms are encouraged as a coding structure.

Standard containers are not object oriented then.

In the standard C++ library it's basically locale and iostreams related
stuff that is OO (or at least has OO aspects), the rest is just abstract
data types.

--
Tristan Wibberley

Any opinion expressed is mine (or else I'm playing devils advocate for
the sake of a good argument). My employer had nothing to do with this
communication.
 
G

Guest

This doesn't make sense. I thought the whole point of Object-Oriented
Programming is that polymophisms are encouraged as a coding structure.

If a derived class can potentially ``damaged'' the integrity of the
base class, then as the designer of the base class he shouldn't have
allowed his methods be declared virtual (so that the derived class
could not override it). If so, how then can any reference of the base
class be using any wrong methods supplied by the derived class?

None of the standard library containers have any virtual functions, most
notably the destructor is not virtual. This is because they were not
designed to be inherited from.
Yea, I like to know too.

If the base class does not have a virtual destructor the derived class's
destructor will not be run when deleting a base class pointer pointing
to a derived object.
 
T

Tristan Wibberley

Standard containers don't have virtual destructors.

That wouldn't be a concern with private inheritance since any pointer to
an instance of the container that might be "delete"ed *must* be
pointer-to-derived class and the correct destructor will be called -
unless the derived class exports a pointer to the base class (which
would be obviously problematic).

--
Tristan Wibberley

Any opinion expressed is mine (or else I'm playing devils advocate for
the sake of a good argument). My employer had nothing to do with this
communication.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top