Linked Class in C++? - c++

As everyone knows: It's possbile to create linkes lists with C / C++ in order to make a program dynamical.
But now, I'm programming a "linked Class" in c++.
My Parent-Class "GAME" should have a variable number of Elements. And each Element is a class.
So I programmed this:
class GAME : public LEVEL
{ private:
ELEMENT *startPointer;
public:
GAME()
{ startPointer=NULL;
}
initGame()
{ p=aStartPointer;
while(p!=NULL);//This loop is based on a linked list, so its dynamic
{ startPointer=new ELEMENT(startPointer);
p=p->next;
}
}
}
class ELEMENT
{ private:
ELEMENT *next;
public:
ELEMENT(ELEMENT* nextPointer)
{ next=nextPointer;
}
}
My Problem: I never heard about a linked class before, and I'm not sure if I should use it.
Does professional programmers use such methods (and is it usefull?), or are there better Methods to do this?

are there better Methods to do this?
Yes. Here is one:
class GAME : public LEVEL
{ private:
std::vector<ELEMENT> elements;
...
};
Use the standard library containers:
Generally, use std::vector<>.
If you need uniqueness, use std::set<>
If you need to associate elements with keys, use std::map<>
If you need to insert or delete items from the container very often or very quickly, use std::list<> or std::set<>
There are other considerations. Consult a good book to learn how to effectively use standard containers.

Looks like you are trying to implement a linked list under a different name. A better design would be to use a list or vector as a member of your class to store the ELEMENTS instead of having it be the basic functionality of the GAME class.
This allows you to have a separation between container-like object and your application classes.

If what you're trying to do is create a container that can contain different types of object instances (ie, a non-homogeneous container), there're several approaches (which generally involve homogenizing the container). You can either set up a common base clase so that you can store handles-to-base. Another option is discriminated unions.
As the other posts mention, the container itself should probably be an STL container, unless you have a really good reason to use something else (and even then, the 'more standard', the better; homebrew is not a good idea unless it is for educational purposes only).

Related

A list containing objects of two different classes in C++

I feel more fluent in Java than C++ so I will try to explain what I want to "transport" in a few words. In Java you could create an ArrayList containing objects of 2 or more classes that one of them inherited from another. Let me illustrate. Let's say we have:
class Vehicle
{
...
}
class Car extends Vehicle
{
...
}
You could then do something like that Car a = new Vehicle ([arguments]);
And then you could add objects of both Vehicle and Car to the same ArrayList created as following:
ArrayList ar = new ArrayList<Car>();
Now to my problem, in C++ I have manually written the code to create a simple linked list. Each node of this list is described below:
struct clientListNode
{
vip* cust;
struct clientListNode* next;
};
vip is another class which is derived from customer.Is there any way to allow my list to accept both objects of vip class and customer class?
Polymorphism works the other way. You can use a customer* pointer to point to a vip object, but not the other way. (This is related to the Liskov-substitution principle.)
So if you had a customer* in your clientListNode class, it would accept both vip* and customer* pointers.
However, I don't think you should reinvent the wheel and implement a linked list from the ground. You should look into the STL (Standard Template Library) which already has solutions for problems like this. For instance, it already has an implementation of the linked list, std::list.
You have to template std::list with the base type you'd like to use it with, but it is important that you cannot use the type directly as a value (std::list<cust>), because that would physically store cust instances in memory, in which you cannot fit the more specific vip type (slicing would occur).
Instead you have to use some kind of handle as the template parameter, you can use a native pointer (std::list<cust*>), but that way you have to manage memory deallocation, or - more preferably - you can use a smart pointer, like shared_ptr (std::list<std::shared_ptr<cust>>), that way the created objects are going to get destroyed automatically.
I doubt you could make Car = new Vehicle even in java, but the other way around makes sense.
What you're after is called "polymorphic collection". C++ standard lib does not have one out of the box, but you can approximate it with a collection of shared_ptr<Vehicle> s or unique_ptr<Vehicle> s. The former would fork very close to a java equivalent.
3rd party libraries may have ready to use polymorphic collections, you can use the term for search.
If customer is the base class, then the cust field of the node should be of type customer*, and it will gladly accept both customers and vips.

Dynamic array of objects in C++

I'm trying to create a dynamic array of objects, similar to ArrayLists in Java. I'm new at C++ and can't get it to work.
class Album{
private:
public:
void addPhoto(Photo p){
}
};
What should my private datamember look like and how do I add p to it? And do I need a pointer for some reason?
The functionality you look for already exits in the stl collection classes and and with out knowing you application it would be had to tell you weather you needed a pointer or not.
The basic layout of you underlying container could be something like this.
class Album{
public:
void addPhoto(Photo p){
Photos.push_back(p);
}
private:
std::vector<Photo> Photos;
};
You should use an std::vector.
You could use the built in std::vector class that behaves very similarly to the ArrayList. (edit... looks like someone beat me to it)
#fontanini gave you a good answer, you should use vector if you need a dynamic array of objects.
But maybe you don't need a class to begin with. Not everything in C++ needs to be encapsulated in a class, unless you really need it.
Think about your data structure and what are the requirements. You might want to learn more about standard C++ library and the STL to familiarize yourself with other containers and their capabilities, limitations and objectives:
There are excellent video lectures on STL "Introduction to STL with Stephan T Lavavej"

Generic Container in C++

I'm attempting to create a generic container type to provide a single common interface, as well as hide the internal containers I'm using as they are subject to change.
Basically I have plugins that return collections of items and I don't wish the plugins to be aware of the type of container my code is using.
Can anyone point me in a better direction then the example code below?
template<class C, typename I>
class Container
{
public:
//...
void push(const I& item)
{
if(typeid(C) == typeid(std::priority_queue<I>))
{
std::priority_queue<I>* container = (std::priority_queue<I>*)&_container;
container->push(item);
}
if(typeid(C) == typeid(std::list<I>))
{
std::list<I>* container = (std::list<I>*)&_container;
container->push_back(item);
}
else
{
//error!
}
};
private:
C _container;
//...
}
Thanks
I have plugins that return collections of items and I don't wish the plugins to be aware of the type of container my code is using.
Have your plugins provide begin and end iterators into their collections of items and then consume the range as you see fit.
The greatest advantage of iterators is that they allow complete decoupling of how the data is stored (the container) from how the data is used (the algorithm; in your case, your application code that consumes the plugin data).
This way, you don't have to care how the plugins store their data and the plugins don't have to care what you do with their data once they give it to you.
You know, when you wrote "common interface", I was sure you were going to show something Java style with an abstract class and subclasses that wrap standard containers. I was surprised to see a bunch of typeid calls...
But then, why do you want to do this? Most containers share a common interface, and with the power of SFINAE, you don't even have to write special code! Just use templates and call the method directly.
EDIT: Forgot that standard containers have no virtual methods and therefore, cannot be dynamic_casted.
Start with a class as above, expose minimal interface needed by your plugins. Then implement it in terms of the container you are going to use. This is called container adapter and it is how std::stack is implemented.
If you really need adapter for more then one STL container go with template, have a look at std::stack, it will show how to do that.
Don't switch on typeid, why would you want that?
BTW, go with what James suggests unless there is a need to expose container itself.

put different class in hierarchy in one container in C++

Some times we have to put different objects in the same hierarchy in one container. I read some article saying there are some tricks and traps. However, I have no big picture about this question. Actually, this happens a lot in the real word.
For example, a parking lot has to contain different types of cars; a zoo has to contain different types of animals; a book store has to contain different types of books.
I remember that one article saying neither of the following is a good design, but I forgot where it is.
vector<vehicle> parking_lot;
vector<*vehicle> parking_lot;
Can anybody offer some basic rules for this kind of question?
I learnt a lot writing my reply to a similar question by the same author, so I couldn't resist to do the same here. In short, I've written a benchmark to compare the following approaches to the problem of storing heterogeneous elements in a standard container:
Make a class for each type of element and have them all inherit from a common base and store polymorphic base pointers in a std::vector<boost::shared_ptr<Base> >. This is probably the more general and flexible solution:
struct Shape {
...
};
struct Point : public Shape {
...
};
struct Circle : public Shape {
...
};
std::vector<boost::shared_ptr<Shape> > shapes;
shapes.push_back(new Point(...));
shapes.push_back(new Circle(...));
shapes.front()->draw(); // virtual call
Same as (1) but store the polymorphic pointers in a boost::ptr_vector<Base>. This is a bit less general because the elements are owned exclusively by the vector, but it should suffice most of the times. One advantage of boost::ptr_vector is that it has the interface of a std::vector<Base> (without the *), so its simpler to use.
boost::ptr_vector<Shape> shapes;
shapes.push_back(new Point(...));
shapes.push_back(new Circle(...));
shapes.front().draw(); // virtual call
Use a C union that can contain all possible elements and then use a std::vector<UnionType>. This is not very flexible as we need to know all element types in advance (they are hard-coded into the union) and also unions are well known for not interacting nicely with other C++ constructs (for example, the stored types can't have constructors).
struct Point {
...
};
struct Circle {
...
};
struct Shape {
enum Type { PointShape, CircleShape };
Type type;
union {
Point p;
Circle c;
} data;
};
std::vector<Shape> shapes;
Point p = { 1, 2 };
shapes.push_back(p);
if(shapes.front().type == Shape::PointShape)
draw_point(shapes.front());
Use a boost::variant that can contain all possible elements and then use a std::vector<Variant>. This is not very flexible like the union but the code to deal with it is much more elegant.
struct Point {
...
};
struct Circle {
...
};
typedef boost::variant<Point, Circle> Shape;
std::vector<Shape> shapes;
shapes.push_back(Point(1,2));
draw_visitor(shapes.front()); // use boost::static_visitor
Use boost::any (which can contain anything) and then a std::vector<boost::any>. That is very flexible but the interface is a little clumsy and error prone.
struct Point {
...
};
struct Circle {
...
};
typedef boost::any Shape;
std::vector<Shape> shapes;
shapes.push_back(Point(1,2));
if(shapes.front().type() == typeid(Point))
draw_point(shapes.front());
This is the code of the full benchmark program (doesn't run on codepad for some reason). And here are my performance results:
time with hierarchy and boost::shared_ptr: 0.491 microseconds
time with hierarchy and boost::ptr_vector: 0.249 microseconds
time with union: 0.043 microseconds
time with boost::variant: 0.043 microseconds
time with boost::any: 0.322 microseconds
My conclusions:
Use vector<shared_ptr<Base> > only if you need the flexibility provided by runtime polymorphism and if you need shared ownership. Otherwise you'll have significant overhead.
Use boost::ptr_vector<Base> if you need runtime polymorphism but don't care about shared ownership. It will be significantly faster than the shared_ptr counterpart and the interface will be more friendly (stored elements not presented like pointers).
Use boost::variant<A, B, C> if you don't need much flexibility (i.e. you have a small set of types which will not grow). It will be lighting fast and the code will be elegant.
Use boost::any if you need total flexibility (you want to store anything).
Don't use unions. If you really need speed then boost::variant is as fast.
Before I finish I want to mention that a vector of std::unique_ptr will be a good option when it becomes widely available (I think it's already in VS2010)
The problem with vector<vehicle> is that the object only holds vehicles. The problem with vector<vehicle*> is that you need to allocate and, more importantly, free the pointers appropriately.
This might be acceptable, depending on your project, etc...
However, one usually uses some kind of smart-ptr in the vector (vector<boost::shared_ptr<vehicle>> or Qt-something, or one of your own) that handles deallocation, but still permits storing different types objects in the same container.
Update
Some people have, in other answers/comments, also mentioned boost::ptr_vector. That works well as a container-of-ptr's too, and solves the memory deallocation problem by owning all the contained elements. I prefer vector<shared_ptr<T>> as I can then store objects all over the place, and move them using in and out of containers w/o issues. It's a more generic usage model that I've found is easier for me and others to grasp, and applies better to a larger set of problems.
The problems are:
You cannot place polymorphic objects into a container since they may differ in size --i.e., you must use a pointer.
Because of how containers work a normal pointer / auto pointer is not suitable.
The solution is :
Create a class hierarchy, and use at least one virtual function in your base class (if you can't think of any function to virtualize, virtualize the destructor -- which as Neil pointed out is generally a must).
Use a boost::shared_pointer (this will be in the next c++ standard) -- shared_ptr handles being copied around ad hoc, and containers may do this.
Build a class hierarchy and allocate your objects on the heap --i.e., by using new. The pointer to the base class must be encapsulated by a shared_ptr.
place the base class shared_pointer into your container of choice.
Once you understand the "whys and hows" of the points above look at the boost ptr_containers -- thanks to Manual for the tip.
Say vehicle is a base class, that has certain properties, then, inheriting from it you have say a car, and a truck. Then you can just do something like:
std::vector<vehicle *> parking_lot;
parking_lot.push_back(new car(x, y));
parking_lot.push_back(new truck(x1, y1));
This would be perfectly valid, and in fact very useful sometimes. The only requirement for this type of object handling is sane hierarchy of objects.
Other popular type of objects that can be used like that are e.g. people :) you see that in almost every programming book.
EDIT:
Of course that vector can be packed with boost::shared_ptr or std::tr1::shared_ptr instead of raw pointers for ease of memory management. And in fact that's something I would recommend to do by all means possible.
EDIT2:
I removed a not very relevant example, here's a new one:
Say you are to implement some kind of AV scanning functionality, and you have multiple scanning engines. So you implement some kind of engine management class, say scan_manager which can call bool scan(...) function of those. Then you make an engine interface, say engine. It would have a virtual bool scan(...) = 0; Then you make a few engines like my_super_engine and my_other_uber_engine, which both inherit from engine and implement scan(...). Then your engine manager would somewhere during initialization fill that std::vector<engine *> with instances of my_super_engine and my_other_uber_engine and use them by calling bool scan(...) on them either sequentially, or based on whatever types of scanning you'd like to perform. Obviously what those engines do in scan(...) remains unknown, the only interesting bit is that bool, so the manager can use them all in the same way without any modification.
Same can be applied to various game units, like scary_enemies and those would be orks, drunks and other unpleasant creatures. They all implement void attack_good_guys(...) and your evil_master would make many of them and call that method.
This is indeed a common practice, and I would hardly call it bad design for as long as all those types actually are related.
You can refer to this Stroustrup's answer to the question Why can't I assign a vector< Apple*> to a vector< Fruit*>?.

C++ alternatives to void* pointers (that isn't templates)

It looks like I had a fundamental misunderstanding about C++ :<
I like the polymorphic container solution. Thank you SO, for bringing that to my attention :)
So, we have a need to create a relatively generic container type object. It also happens to encapsulate some business related logic. However, we need to store essentially arbitrary data in this container - everything from primitive data types to complex classes.
Thus, one would immediately jump to the idea of a template class and be done with it. However, I have noticed C++ polymorphism and templates do not play well together. Being that there is some complex logic that we are going to have to work, I would rather just stick with either templates OR polymorphism, and not try to fight C++ by making it do both.
Finally, given that I want to do one or the other, I would prefer polymorphism. I find it much easier to represent constraints like "this container contains Comparable types" - a la java.
Bringing me to the topic of question: At the most abstract, I imagine that I could have a "Container" pure virtual interface that has something akin to "push(void* data) and pop(void* data)" (for the record, I am not actually trying to implement a stack).
However, I don't really like void* at the top level, not to mention the signature is going to change every time I want to add a constraint to the type of data a concrete container can work with.
Summarizing: We have relatively complex containers that have various ways to retrieve elements. We want to be able to vary the constraints on the elements that can go into the containers. Elements should work with multiple kinds of containers (so long as they meet the constraints of that particular container).
Edit: I should also mention that the containers themselves need to be polymorphic. That is my primary reason for not wanting to use templated C++.
So - should I drop my love for Java type interfaces and go with templates? Should I use void* and statically cast everything? Or should I go with an empty class definition "Element" that declares nothing and use that as my top level class in the "Element" hierarchy?
One of the reasons why I love stack overflow is that many of the responses provide some interesting insight on other approaches that I hadn't not have even considered. So thank you in advance for your insights and comments.
You can look at using a standard container of boost::any if you are storing truly arbitrary data into the container.
It sounds more like you would rather have something like a boost::ptr_container where anything that can be stored in the container has to derive from some base type, and the container itself can only give you reference's to the base type.
The simple thing is to define an abstract base class called Container, and subclass it for each kind of item you may wish to store. Then you can use any standard collection class (std::vector, std::list, etc.) to store pointers to Container. Keep in mind, that since you would be storing pointers, you would have to handle their allocation/deallocation.
However, the fact that you need a single collection to store objects of such wildly different types is an indication that something may be wrong with the design of your application. It may be better to revisit the business logic before you implement this super-generic container.
Polymorphism and templates do play very well together, if you use them correctly.
Anyway, I understand that you want to store only one type of objects in each container instance. If so, use templates. This will prevent you from storing the wrong object type by mistake.
As for container interfaces: Depending on your design, maybe you'll be able to make them templated, too, and then they'll have methods like void push(T* new_element). Think of what you'll know about the object when you want to add it to a container (of an unknown type). Where will the object come from in the first place? A function that returns void*? Do you know that it'll be Comparable? At least, if all stored object classes are defined in your code, you can make them all inherit from a common ancestor, say, Storable, and use Storable* instead of void*.
Now if you see that objects will always be added to a container by a method like void push(Storable* new_element), then really there will be no added value in making the container a template. But then you'll know it should store Storables.
Can you not have a root Container class that contains elements:
template <typename T>
class Container
{
public:
// You'll likely want to use shared_ptr<T> instead.
virtual void push(T *element) = 0;
virtual T *pop() = 0;
virtual void InvokeSomeMethodOnAllItems() = 0;
};
template <typename T>
class List : public Container<T>
{
iterator begin();
iterator end();
public:
virtual void push(T *element) {...}
virtual T* pop() { ... }
virtual void InvokeSomeMethodOnAllItems()
{
for(iterator currItem = begin(); currItem != end(); ++currItem)
{
T* item = *currItem;
item->SomeMethod();
}
}
};
These containers can then be passed around polymorphically:
class Item
{
public:
virtual void SomeMethod() = 0;
};
class ConcreteItem
{
public:
virtual void SomeMethod()
{
// Do something
}
};
void AddItemToContainer(Container<Item> &container, Item *item)
{
container.push(item);
}
...
List<Item> listInstance;
AddItemToContainer(listInstance, new ConcreteItem());
listInstance.InvokeSomeMethodOnAllItems();
This gives you the Container interface in a type-safe generic way.
If you want to add constraints to the type of elements that can be contained, you can do something like this:
class Item
{
public:
virtual void SomeMethod() = 0;
typedef int CanBeContainedInList;
};
template <typename T>
class List : public Container<T>
{
typedef typename T::CanBeContainedInList ListGuard;
// ... as before
};
First, of all, templates and polymorphism are orthogonal concepts and they do play well together. Next, why do you want a specific data structure? What about the STL or boost data structures (specifically pointer containter) doesn't work for you.
Given your question, it sounds like you would be misusing inheritance in your situation. It's possible to create "constraints" on what goes in your containers, especially if you are using templates. Those constraints can go beyond what your compiler and linker will give you. It's actually more awkward to that sort of thing with inheritance and errors are more likely left for run time.
Using polymorphism, you are basically left with a base class for the container, and derived classes for the data types. The base class/derived classes can have as many virtual functions as you need, in both directions.
Of course, this would mean that you would need to wrap the primitive data types in derived classes as well. If you would reconsider the use of templates overall, this is where I would use the templates. Make one derived class from the base which is a template, and use that for the primitive data types (and others where you don't need any more functionality than is provided by the template).
Don't forget that you might make your life easier by typedefs for each of the templated types -- especially if you later need to turn one of them into a class.
You might also want to check out The Boost Concept Check Library (BCCL) which is designed to provide constraints on the template parameters of templated classes, your containers in this case.
And just to reiterate what others have said, I've never had a problem mixing polymorphism and templates, and I've done some fairly complex stuff with them.
You could not have to give up Java-like interfaces and use templates as well. Josh's suggestion of a generic base template Container would certainly allow you do polymorphically pass Containers and their children around, but additionally you could certainly implement interfaces as abstract classes to be the contained items. There's no reason you couldn't create an abstract IComparable class as you suggested, such that you could have a polymorphic function as follows:
class Whatever
{
void MyPolymorphicMethod(Container<IComparable*> &listOfComparables);
}
This method can now take any child of Container that contains any class implementing IComparable, so it would be extremely flexible.