I'm coming from the Java world and are building a small c++ program at the moment. I have an object that does some work and then returns the result of the work as a list.
Now a day later i changed the behavior of the object to save the results in a set to avoid duplicates in the container. But I can't simply return the set because I used a list for the interface in the first time. Is there a common container interface that I can use to specify the interface of my object and forget about the container type I use internally?
At the moment I'm creating a set adding all the values and then creating a list from the set:
return std::list<foo>(this->mySet.begin(), this->mySet.end())
Seems a little strange.
The concept of a container is enbodied by iterators.
As you have seen hard coding a specific type of container is probably not what you want. So make your class return iterators. You can then re-use the conatiners iterators.
class MyClass
{
private:
typedef std::list<int> Container;
public:
typedef Container::iterator iterator;
typedef Container::const_iterator const_iterator;
iterator begin() {return myData.begin();}
const_iterator begin() const {return myData.begin();}
iterator end() {return myData.end();}
const_iterator end() const {return myData.end();}
private:
Container myData;
};
Now when you change the Container type from std::list to std::set nobody needs to know.
Also by using the standard names that other containers use your class starts to look like any other container from the STL.
Note: A method that returns a const_iterator should be a const method.
The whole C++- standard library including its containers is - unlike Java - not interface (inheritance, polymorphism)- but template-based (for the sake of efficiency).
You could create a polymorphic wrapper around your collection but this isn't the C++-way.
The simplest solution is just to simplify the programm with some type aliases:
#include <iostream>
#include <list>
#include <vector>
using namespace std;
class Test {
private:
typedef vector<int> Collection;
Collection c;
public:
typedef Collection::const_iterator It;
void insert(int Item) {
c.push_back(Item);
}
It begin() const { return c.begin(); }
It end() const { return c.end(); }
};
int main() {
Test foo;
foo.insert(23);
foo.insert(40);
for (Test::It i = foo.begin(); i != foo.end(); ++i)
cout << *i << endl;
return 0;
}
You can now change the Collection
-typedef without having to change anything else. (Note: If you make Collection
public, the user will be able to refer the the type you used explicitly)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With