containers jason goffeney 2/23/2006. containers the stl is a standard part of probably all c++...
TRANSCRIPT
Containers
Jason Goffeney
2/23/2006
Containers
• The STL is a standard part of probably all C++ implementations
• It features implementations of most of the handy basic container classes, such as, linked lists, vectors, and hashes.
• Qt also implements many of these containers as well as many more.
• STL classes will work with any C++ code while Qt classes will only work with Qt/C++ code.
Containers
• How to include in your program.– STL classes use C++ style includes (which
means you leave the .h off its header file).• #include <vector>• #include <list>
– Qt 4.0 classes also use C++ style include but also have capitalization
• #include <QVector>• #include <QList>
Containers
• How to include in your program.– Note: STL classes are in the std namespace
which means that you usually need to prepend std:: to each STL keyword when using it
• std::vector<int> newVector
– If you want to avoid doing this then follow your STL includes with using namespace std;
#include <vector>#include <list>Using namespace std;
Containers
• Both STL and Qt containers are designed as templates which take a class or struct as a parameter for their declaration.
• For example, suppose you have a class called Point and want to make a list of points– STL: list<Point> pointList;– Qt: QList<Point> pointList;
Containers
• This will also work for primitive types such as int, float, char, etc.– STL: list<int> pointList;– Qt: QList<float> floatList;
• If you want to create them as pointers than you can do that too.– STL: list<int> * pointList = new list<int>();– Qt: QList<float> * floatList = new QList<float>();
Containers: Style Notes
• If a container will need to exist outside of the scope of a single function then it is generally declared in the class definition in the header file (usually in the private section).
• For a non-pointer container then you are done and can just use it in the rest of your code.
• For a pointer declare it in the header and create the container in the constructor of the source file.– In Header: QVector<Point> * ptList;– In Constructor: ptList = new QVector<Point>();
Containers: Style Notes
• For the remainder of this I will likely assume non-pointers and use a “.” to show access to methods of the containers.
• But pointers are useful and speed up passing containers into functions. The take home point though is that “->” is used to access methods from pointers.
Containers: Vector
• Vectors are simple dynamically expandable and collapsible lists.
• Operations:– Construct:
• STL: vector<float> myVector;• Qt: QVector<float> myVector;
– Add an element to the end• STL: myVector.push_back(5.34);• Qt: myVector.append(5.34);
Containers: Vector
• Operations:– Insert (position, item):
• STL, Qt: myVector.insert(2, 4.35);
– Remove an element (position):• STL: myVector.erase(5);• Qt: myVector.remove(5);
– Access an element (position):• STL/Qt: float f1 = myVector.at(3);• myVector.at(0) = 3.67;
Containers: Vector
• Operations:– Get current size of vector
• STL, Qt: int size = myVector.size();
– Get first element• STL, Qt: float first = myVector.front();
– Get last element• STL, Qt: float first = myVector.back();
Containers: Vector
• Operations:– Iterating through a vector
• There are two ways to iterate through vectors
– The old way:for(i = 0; i < myVector.size(); i++){ printf( “The float is %f\n”, myVector.at(i));}
– Problem: If you remove elements from the list while iterating bad things may happen
Containers: Vector• STL Iterators:
vector<int> myIntVector; vector<int>::iterator myIntVectorIterator; //Iterator object for list
// Add some elements to myIntVectormyIntVector.push_back(1);myIntVector.push_back(4); myIntVector.push_back(8);
for(myIntVectorIterator = myIntVector.begin(); myIntVectorIterator != myIntVector.end(); myIntVectorIterator++) { cout<<*myIntVectorIterator<<" "; //Should output 1 4 8 }
Containers: Vector
• Qt Iterators:
QVector<float> vector;
...
QVectorIterator<float> i(vector);
while (i.hasNext())
{
cout << i.next();
}
Containers: Vector
• These are a few of the ways it is possible to manipulate STL and Qt Vector containers.
• Look at their references to learn more.
Other Containers:
• Lists – Doubly linked list that support faster insertions and deletions than vector.
• Hashes – A container that stores and retrieves an item by a key. Allows for very fast lookups of items but only a single item can be stored per key
• Multihash – Like a hash except multiple objects can be stored per key with
• Stacks, Queues, etc…
Example
• One of the basic model formats is the Alias .obj format. It defines a list of vertex coordinates and then a list of faces and the indices of the vertices that compose them.
0. (0,0) 1. (50,0)
3. (50,50)2. (0,50)
Verticesv 0 0v 50 0v 0 50v 50 50
Facef 0 1 2f 1 3 2
Example
• I want a way to store my simple model use later. So I need to make some classes or structures.
• s are simple to represent as a couple of Integers. (Note: the QPoint class already exists in Qt).
struct Point2i{ //A point that holds 2 integer values int x, y;};
Example
• I want a way to store my simple model use later. So I need to make some classes or structures.
• Vertices are simple to represent as a couple of Integers. (Note: the QPoint class already exists in Qt).
class Vertex2i{ public: //Constructor Vertex2i(int xi, int yi)(x = xi; y = yi;}
//A point that holds 2 integer values int x, y;};
Example
• A face can be composed of any number of vertices so a list of point indices could be useful here.
class Face{ public: //A face holds ? vertices vector<int> vertices;};
Example
• I will load my vertices into a vector of vertices.
vector<Vertex2i> vertexList;
Vertex2i v0(0,0);Vertex2i v1(50,0);Vertex2i v2(0,50);Vertex2i v3(50,50);
vertexList.push_back(v0);vertexList.push_back(v1);vertexList.push_back(v2);vertexList.push_back(v3);
Example
• I will build my Faces and load them into a list as well. vector<Face> faceList;
Face f1;f1.vertices.push_back(0);f1.vertices.push_back(1);f1.vertices.push_back(2);
Face f2;f2.vertices.push_back(1);f2.vertices.push_back(3);f2.vertices.push_back(2);
faceList.push_back(f1);faceList.push_back(f2);
Example
• Now I want to draw the faces.
for(int j = 0; j < faceList.size(); j++){ glBegin(GL_LINE_LOOP); //Start drawing
vector<int> tempList = faceList.at(j).vertices; for(int m = 0; m < tempList.size(); m++) { int vIdx = tempList.at(m); glVertex2i( vertexList.at(vIdx).x, vertexList.at(vIdx).y); }
glEnd(); //Stop drawing}
Example
• If you want to try it:– Put the Vertex2i and Face class definitions in
the top of your GLWidget.h below the includes.
– Declare the vectors in your GLWidget class with the appropriate includes.
– In the GLWidget constructor put all the loading code
– In the GLWidget paintGL method put the drawing code right below the glClear statement
Example
• Generally, a model will be loaded from a file which makes the vector filling less tedious.
• Notice that by adding a z coordinate to he Vertex class this will easily handle 3D models as well.