Base class vector filled with sub-classes not working - c++

I'm trying to have a vector of different subclass pointers that have a common base class. The vector is set to the base class pointer but anything that is added to the vector doesn't get the full functionality of the subclass it is.
It can be seen in the error log it is being treated as a base class so not getting the extended functionality.
I've looked on loads of questions and people are saying to do it the way I am doing it, but for whatever reason, it's not working.
The code is on a public repo.it:
https://repl.it/#cubingminer8/inheritance-with-vectors-testing
Any help would be greatly appreciated!
edit: ok so I'm going to use this for a sprite group system in a c++ sdl2 game engine. There will be a base sprite class that has some basic things like render and move, while any sprites I need will be their own classes that inherit from Sprite, they will have their own unique behaviors so virtual functions would be impractical. There will be a sprite group object, that objects that inherit from Sprite can be stored in. So they can all be rendered at once and such.
If you have ever used pygame then it is almost identical to the sprite and spritegroup system used there.
https://www.pygame.org/docs/tut/SpriteIntro.html
#include <iostream>
#include <vector>
class Base {
public:
char A = 'A';
};
class Sub : public Base {
public:
char B = 'B';
};
class Sub2 : public Base {
public:
char C = 'C';
};
int main() {
std::vector<Base*> List;
List.push_back(new Sub());
List.push_back(new Sub2());
std::cout << List[0]->B << std::endl; // it should be able to print B
std::cout << List[1]->C << std::endl; // but it is being set as a base class and
// not getting the functionality of the subclass it is.
}

Usually, this is achieved by virtual functions. In the given case it should be a virtual getter function which returns the char members of each class.
class Base {
char A = 'A';
public:
virtual char getChar()const /*noexcept*/ { return A; }
virtual Base () = default;
};
class Sub : public Base {
char B = 'B';
public:
char getChar()const /*noexcept*/ override { return B; }
};
class Sub2 : public Base {
char C = 'C';
public:
char getChar()const /*noexcept*/ override { return C; }
};
now in the main
std::cout << List[0]->getChar() << std::endl;
As a side note, I suggest you to have a look at smart pointers, instead of the row pointers, by which you can avoid manual memory management.
A good starting would be:
#include <memory>
std::vector<std::unique_ptr<Base>> List;
List.emplace_back(std::make_unique<Sub>());

So you want this to work:
// your code version 1
std::cout<< List[0]->B << std::endl; //it should be able to print B
std::cout<< List[1]->C << std::endl; //but it is being set as a base class
But what should happen if you write this instead?
// your code version 2
std::cout<< List[0]->C << std::endl;
std::cout<< List[1]->B << std::endl;
List[0] doesn't have any C and List[1] doesn't have any B. How do you propose to treat this code?
There are several ways to approach this.
The compiler should know at compilation time that version 1 is right, and version 2 is wrong. Unfortuantely this is generally impossible because the compiler cannot keep track of what object pointer goes to which slot in the array. So this has to be dismissed.
The run time system should detect the error at run time. This is a possible approach, but not one taken by C++. C++ is a statically typed language. Dynamically typed languages can handle this case. If you want a dynamically typed language, try e.g. Python.
The compiler should not try to detect anything, and the runtime system should not try to detect anything either, but go ahead and perforrm the operation anyway, and let it produce wrong results or crash. This is also a possible approach, but not one taken by any modern high-level programming language. C++ and other modern languages are typed. It is possible to circumvent the type system of C++ by using reinterpret_cast and the like, but this is very dangerous and is not recommended.
The compiler should treat both versions as wrong. This is what C++ does.
As others have mentioned, the (only) right way to extend functionality of a class is via virtual functions. This requires some planning ahead. The base should at least declare which operations are needed, though it doesn't need to know how derived classes will implement them.

Related

Advice for best approach at extending class capability

I want to extend a class to include extra data and capabilities (I want polymorphic behavior). It seemed obvious to use inheritance and multiple inheritance.
Having read various posts that inheritance (and especially multiple inheritance) can be problematic, I've begun looking into other options:
Put all data and functions in one class and not use inheritance
Composite pattern
mixin
Is there a suggested approach for the following inheritance example? Is this a case where inheritance is reasonable? (but I don't like having to put default functions in the base-class)
#include <iostream>
//================================
class B {
public:
virtual ~B() { }
void setVal(int val) { val_ = val; }
// I'd rather not have these at base class level but want to use
// polymorphism on type B:
virtual void setColor(int val) { std::cout << "setColor not implemented" << std::endl; }
virtual void setLength(int val) { std::cout << "setLength not implemented" << std::endl; }
private:
int val_;
};
//================================
class D1 : virtual public B {
public:
void setColor(int color) {
std::cout << "D1::setColor to " << color << std::endl;
color_ = color;
}
private:
int color_;
};
//================================
class D2 : virtual public B {
public:
void setLength(int length) {
std::cout << "D2::setLength to " << length << std::endl;
length_ = length;
}
private:
int length_;
};
//================================
// multi-inheritance diamond - have fiddled with mixin
// but haven't solved using type B polymorphically with mixins
class M1 : public D1, public D2 {
};
//================================
int main() {
B* d1 = new D1;
d1->setVal(3);
d1->setColor(1);
B* m1 = new M1;
m1->setVal(4);
m1->setLength(2);
m1->setColor(4);
return 0;
}
Suspected problems with the original example code
There are a number of issues with your example.
In the first place, you don't have to supply function bodies in the base class. Use pure virtual functions instead.
Secondly, both your classes D1 and D2 miss functionality, so they should be abstract (which will prevent you from creating deprived objects from them). This second issue will become clear if you indeed use pure virtual functions for your base class. The compiler will start to issue warnings then.
Instantiating D1 as you do with new D1, is bad design, because D1 has no truly functional implementation of the setLength method, even if you give it a 'dummy' body. Giving it a 'dummy' body (one that doesn't do anything useful) so masks your design error.
So your remark (but I don't like having to put default functions in the base-class) testifies of a proper intuition. Having to do that signals flawed design. A D1 object cannot understand setLength, while its inherited public interface promises it can.
And: There's nothing wrong with multiple inheritance, if used correctly. It is very powerful and elegant. But you have to use it where appropiate. D1 and D2 are partial implementations of B, so abstract, and inheriting from both will indeed give you a complete implementation, so concrete.
Maybe a good rule to start with is: Use multiple inheritance only if you see a compelling need for it. But if you do, as said, it's very useful. It can prevent quite some ugly asymmetry and code duplication, compared to e.g. a language like Java, that has banned it.
I am not a tree doctor. When I use a chainsaw I endanger my leg. But that is not to say chainsaws ain't useful.
Where to put the dummy: Nowhere please, do not disinherit...
[EDIT after first comment of OP]
If you derive a class D1 from B that would print 'setLength not implemented' if you call its setLength method, how should the caller react? It shouldn't have called it in the first place, which the caller could have known if D1 did not derive from a B that has this methods, pure virtual or not. Then it would have been clear that it just doesn't support this method. Having the B baseclass makes D1 feel at home in a polymorphic datastructure who'se element type, B* or B&, promises its users that its objects properly support getLength, which they don't.
While this is not the case in your example (but maybe you left things out), there may of course be a good reason to derive D1 and D2 from B. B could hold a part of the eventual interface or implementation of its derived classes that both D1 an D2 need.
Suppose B had a method setAny (key, value) (setting a value in a dictionary), which D1 and D2 both use, D1 calls it in setColor and D2 calls it in setLength.
In that case use of a common base class is justified. In that case B should not have virtual methods setColor or setLength at all, neither dummies nor pure. You should just have a setColor in your D1 class and a setLength in your D2 class, but neither of both in your B class.
There's a basic rule in Object Oriented Design:
Do not disinherit
By introducing the concept of a "method that's not applicable" in a concrete class that's just what you're doing. Now rules like this aren't dogma's. But violating this rule almost always points to a design flaw.
All B's in one datastructure is only useful to have them do a trick that they all understand...
[EDIT2 after second coment of OP]
OP wants to have a map that can hold objects of any class derived from B.
This is exactly where the problem starts. To find out how to store pointers and references to our objects, we have to ask: what is the storage used for. If a map, say mapB is used to store pointers to B, there must be some point in that. With data storage the fun is in retrieving the data and doing something useful with it.
Let's make this a bit simpler by working with lists from everyday life. Suppose I have a personList of say 1000 persons, each with their fullName and phoneNumber. And now say I have a problem with the kitchen sink. I could in fact read through the list, call every single Person on it and ask: can you repair my kitchen sink. In other words: do you support the repairKitchenSink method. Or: are you by any chance an instance of class Plumber (are you a Plumber). But then I spend quite some time calling, and maybe after 500 calls or so, I'll be lucky.
Now all 1000 persons on my personList do support the talkToMe method. So whenever I feel lonely I can call any person from that list and invokate that Person's talkToMe method. But they should not all have a repairKitchenSink method, even not a pure virtual or a dummy variation that does something else, because if I would call this method for a person of class Burglar, he'd probably respond to the call, but in an unexpected way.
So class Person shouldn't contain a method repairKitchenSink, even not a pure virtual one. Because it should never called as part of iteration of personList. It should be called when iterating plumberList. This lists only holds objects that support the repairKitchenSink method.
Use pure virtual functions only where appropriate
They may support it in different ways though. In other words, in class Plumber, method repairKitchenSink can e.g. be pure virtual. There may e.g. be 2 derived classes, PvcPlumber and CopperPlumber. CopperPlumber would implement (code) the repairKitchenSink method by calling lightFlame, followed by a call to solderDrainToSink whereas PvcPlumber would implement it as successive calls to applyGlueToPvcTube and glueTubeToSinkOutlet. But both plumber subclasses implement repairKitchenSink, only in different ways. This and only this justifies having the pure virtual function repairKitchenSink in their base class Plumber. Now of course a class may be derived from Plumber that doesn't implement that method, say class WannabePlumber. But since it will be abstract, you cannot instantiate objects from it, which is good, unless you want wet feet.
There may be many different subclasses of Person. They e.g. represent different professions, or different political preferences, or different religions. If a Person is a Democrat Budhist Plumber, than he (M/F) may be in a derived class that inherits from classes Democrat, Budhist and Plumber. Using inheritance or even typing for something so volatile as political preferences or religious beliefs, or even profession and the endless amount of combinations of those, would not be handy in practice, but it's just an example. In reality profession, religion and politicalPreference would probably be attributes. But that doesn't change the point that matters here. IF something is of a class does not support a certain operation, THEN it shouldn't be in a datastructure that suggests it does.
By, besides personList, having plumberList, animistList and democratList, you're sure to call a person that understands your call to method inviteBillToPlayInMyJazzBand, or worshipTheTreeInMyBackyard.
Lists don't contain objects, they only contain pointers or references to objects. So there's nothing wrong with our Democratic Budhist Plumber being contained in personList, democratList, budhistList and plumberList. Lists are like database indexes. The don't contain the records, they just refer to them. You can have many indexes on one table, and you should, because indexes are small and make your database fast.
The same holds for polymorphic datastructures. At the moment that even personList, democratList, budhistList and plumberList become so large that you're running out of memory, the solution is generally NOT to only have a personList. Because then you exchange your memory problem for a perfomance problem and a code complexity problem that, in general, is far worse.
So, back to your comment: You say you want all your derived classes to be in a list of B's. Fine, but still the interface of a B should only contain methods that are implemented for everything in the list, so no dummy methods. That would be like going through the library and going through all books, in search for one that supports the teachMeAboutTheLovelifeOfGoldfishes method.
To be honest, in telling you all this, I've been committing a capital sin. I've been selling general truths. But in software design these don't exist. I've been trying to sell them to you because I've been teaching OO design for some 30 years now, and I think I recognize the point where your stuck. But to every rule there are many exceptions. Still, if I've properly fathomed your problem, in this case I think you should go for separate datastructures, each holding only references or pointers to objects that really can do trick that you were after when you iterated through that particular datastructure.
A point is a square circle
Part of the confusion in properly using polymorphic datastructures (datastructures holding pointers or references to different object types) comes for the world of relational databases. RDB's work with tables of flat records, each record having the same fields. Since some fields may not apply, something called 'constraint' was invented. In C++ class Point would contain field x and y. Class Circle could inherit from it and additionally contain field 'radius'. Class Square could also inherit from Point, but contain field 'side' in addition to x and y. In the RDB world constraints, not fields, are inherited. So a Circle would have constraint radius == 0. And a Square would have constraint side == 0. And a Point would inherit both constraints, so it would meet the conditions for both being a square and a circle: A point is a square circle, which in mathematics indeed is the case. Note that the constraint inheritance hierarchy is 'upside down', compared to C++. Which can be confusing.
What doesn't help either is the generally held belief that inheritance goes hand in hand with specialization. While this is often the case it isn't always. In many cases in C++ inheritance is extension rather than specialization. The two often coincide, but the Point, Square, Circle example shows that this isn't a general truth.
If inheritance is used, in C++ Circle should derive from Point, since it has extra fields. But a Circle certainly isn't a special type of Point, it's the other way round. In many practical libraries, by the way, Circle will contain an object of class Point, holding x and y, rather than inherit from it, bypassing the whole problem.
Welcome to the world of design choices
What you bumped into is a real design choice, and an important one. Thinking very carefully about things like this, as you are doing, and trying them all in practice, including the allegedly 'wrong' ones, will make you a programmer, rather than a coder.
Let me first state that what you are trying to do is a design smell: Most probably what you are actually trying to achieve could be achieved in a better way. Unfortunately we can't know what it is you actually want to achieve since you only told us how you want to achieve it.
But anyway, your implementation is bad, as the methods report "not implemented" to the users of the program, rather than to the caller. There is no way for the caller to react on the method not doing what is intended. Even worse, you don't even output it to the error stream, but to the regular output stream, so if you use that class in any program that produces regular output, that output will be interrupted by your error message, possibly confusing a program further on in a pipeline).
Here's a better way to do it:
#include <iostream>
#include <cstdlib> // for EXIT_FAILURE
//================================
class B {
public:
virtual ~B() { }
void setVal(int val) { val_ = val; }
// note: No implementation of methods not making sense to a B
private:
int val_;
};
//================================
class D1 : virtual public B {
public:
void setColor(int color) {
std::cout << "D1::setColor to " << color << std::endl;
color_ = color;
}
private:
int color_;
};
//================================
class D2 : virtual public B {
public:
void setLength(int length) {
std::cout << "D2::setLength to " << length << std::endl;
length_ = length;
}
private:
int length_;
};
class M1 : public virtual D1, public virtual D2 {
};
//================================
int main() {
B* d1 = new D1;
p->setVal(3);
if (D1* p = dynamic_cast<D1*>(d1))
{
p->setColor(1);
}
else
{
// note: Use std::cerr, not std::cout, for error messages
std::cerr << "Oops, this wasn't a D1!\n";
// Since this should not have happened to begin with,
// better exit immediately; *reporting* the failure
return EXIT_FAILURE;
}
B* m1 = new M1;
m1->setVal(4);
if (D2* p = dynamic_cast<D2*>(m1))
{
p->setLength(2);
}
else
{
// note: Use std::cerr, not std::cout, for error messages
std::cerr << "Oops, this wasn't a D1!\n";
// Since this should not have happened to begin with,
// better exit immediately; *reporting* the failure
return EXIT_FAILURE;
}
if (D1* p = dynamic_cast<D1*>(m1))
{
p->setColor(4);
}
else
{
// note: Use std::cerr, not std::cout, for error messages
std::cerr << "Oops, this wasn't a D1!\n";
// Since this should not have happened to begin with,
// better exit immediately; *reporting* the failure
return EXIT_FAILURE;
}
return 0;
}
Alternatively, you could make use of the fact that your methods share some uniformity, and use a common method to set all:
#include <iostream>
#include <stdexcept> // for std::logic_error
#include <cstdlib>
#include <string>
enum properties { propValue, propColour, propLength };
std::string property_name(property p)
{
switch(p)
{
case propValue: return "Value";
case propColour: return "Colour";
case propLength: return "Length";
default: return "<invalid property>";
}
}
class B
{
public:
virtual ~B() {}
// allow the caller to determine which properties are supported
virtual bool supportsProperty(property p)
{
return p == propValue;
}
void setProperty(property p, int v)
{
bool succeeded = do_set_property(p,v);
// report problems to the _caller_
if (!succeeded)
throw std::logic_error(property_name(p)+" not supported.");
}
private:
virtual bool do_set_property(property p)
{
if (p == propValue)
{
value = v;
return true;
}
else
return false;
}
int value;
};
class D1: public virtual B
{
public:
virtual bool supportsProperty(property p)
{
return p == propColour || B::supportsProperty(p);
}
private:
virtual bool do_set_property(property p, int v)
{
if (p == propColour)
{
colour = v;
return true;
}
else
return B::do_set_property(p, v);
}
int colour;
};
class D2: public virtual B
{
public:
virtual bool supportsProperty(property p)
{
return p == propLength || B::supportsProperty(p);
}
private:
virtual bool do_set_property(property p, int v)
{
if (p == propLength)
{
length = v;
return true;
}
else
return B::do_set_property(p, v);
}
int length;
};
class M1: public virtual D1, public virtual D2
{
public:
virtual bool supportsProperty(property p)
{
return D1::supportsProperty(p) || D2::supportsProperty(p);
}
private:
bool do_set_property(property p, int v)
{
return D1::do_set_property(p, v) || D2::do_set_property(p, v);
}
};

Cast relatives classes to each other which has common parent class

I have classes DBGameAction and ServerGameAction which has common parent class GameAction. Classes DBGameAction and ServerGameAction it's a API for safety working with entity GameAction from different part of program.
My question is: is it normal at first create DBGameAction entity and then cast it to the ServerGameAction entity? Or maybe it's a wrong program design?
My program:
#include <vector>
#include <string>
#include <iostream>
class GameAction
{
protected:
/* Need use mutex or something else for having safety access to this entity */
unsigned int cost;
unsigned int id;
std::vector<std::string> players;
GameAction(){}
public:
unsigned int getCost() const
{
return cost;
}
};
class DBGameAction : public GameAction
{
public:
void setCost(unsigned int c)
{
cost = c;
}
void setId(unsigned int i)
{
id = i;
}
};
class ServerGameAction : public GameAction
{
ServerGameAction(){}
public:
void addPlayer(std::string p)
{
players.push_back(p);
}
std::string getLastPlayer() const
{
return players.back();
}
};
int main(int argc, char *argv[])
{
DBGameAction *dbga = 0;
ServerGameAction *sga = 0;
try {
dbga = new DBGameAction;
}
catch(...) /* Something happens wrong! */
{
return -1;
}
sga = reinterpret_cast<ServerGameAction*>(dbga);
sga->addPlayer("Max");
dbga->setCost(100);
std::cout << dbga->getCost() << std::endl;
std::cout << sga->getLastPlayer() << std::endl;
delete dbga;
sga = dbga = 0;
return 0;
}
It is wrong program design.
Is there a reason why you are not creating GameAction variables which you then downcast to DBGameAction and ServerGameAction?
I haven't used reinterpret_cast in many occasions but I am sure it shouldn't be used this way. You should try to find a better design for the interface of your classes. Someone who uses your classes, doesn't have a way to know that he needs to do this sort of castings to add a player.
You have to ask yourself, if adding a player is an operation that only makes sense for ServerGameActions or for DBGameActions too. If it makes sense to add players to DBGameActions, then AddPlayer should be in the interface of DBGameAction too. Then you will not need these casts. Taking it one step further, if it is an operation that makes sense for every possible GameAction you may ever have, you can put it in the interface of the base class.
I have used a similar pattern effectively in the past, but it is a little different than most interface class setups. Instead of having a consistent interface that can trigger appropriate class-specific methods for accomplishing similar tasks on different data types, this provides two completely different sets of functionality which each have their own interface, yet work on the same data layout.
The only reason I would pull out this design is for situations where the base class is data-only and shared between multiple libraries or executables. Then each lib or exe defines a child class which houses all the functionality that it's allowed to use on the base data. This way you can, for example, build your server executable with all kinds of nice extra functions for manipulating game data that the client isn't allowed to use, and the server-side functionality doesn't get built into the client executable. It's much easier for a game modder to trigger existing, dormant functionality than to write and inject their own.
The main part of your question about casting directly between the child classes is making us worry, though. If you find yourself wanting to do that, stop and rethink. You could theoretically get away with the cast as long as your classes stay non-virtual and the derived classes never add data members (the derived classes can't have any data for what you're trying to do anyway, due to object slicing), but it would be potentially dangerous and, most likely, less readable code. As #dspfnder was talking about, you would want to work with base classes for passing data around and down-cast on-demand to access functionality.
With all that said, there are many ways to isolate, restrict, or cull functionality. It may be worth reworking your design with functionality living in friend classes instead of child classes; that would require much less or no casting.

Draw on canvas from within C++ XPCOM code

Is it possible to draw on element from C++ XPCOM add-on?
Previously (long time ago probably) one could get an object of nsIDOMCanvasRenderingContext2D interface and use ti's method PutImageData_explicit in order to draw image on canvas. Nowadays, nsIDOMCanvasRenderingContext2D hides everything and I have no clue how to achieve this.
In general - is there a way to render a video (let's say obtained from remote host) by add-on on a web-page?
Any advice will be appreciated.
Thank you
There is PutImageData_explicit now. But that is a protected member.
You may cheat the system and break the encapsulation for your purposes, e.g. by deriving and downcasting (and now protected members are all yours).
Or do it the hard way, and use PutImageData while having to mess around with ImageData and ErrorResult.
Downcasting to get to a protected member:
#include <string>
#include <iostream>
class Base {
protected:
std::string myName() {
return "Base";
}
};
class Derived : public Base {
public:
std::string myName() {
return Base::myName();
}
};
int main() {
Base *base = new Base();
Derived* derived = static_cast<Derived*>(base);
std::cout << derived->myName() << std::endl;
delete base;
return 0;
}
PS: This works, because this still holds true sizeof(Base) == sizeof(Derived). You really don't want to modify the size, e.g. by adding data members or such, unless you're a fan of segfault and heap corruption ;)

Is passing(in constructor) a pointer to class that contains it a bad design and if so what is the solution

often I encounter code like
/*initializer list of some class*/:m_member(some_param,/* --> */ *this)
Reason why this is done is so that m_member can call member functions from the class that contains it...
aka
//code in class that is m_member instance of
m_parent->some_function();
I personally dislike it because I consider it pathetic design("dear child do you know what are you doing to your class encapsulation"), but I would like to know is in general this behavior bad, and if so how to avoid this kind of design.
EDIT: please dont focus on this in initalizer list, lets say it is in ctor body.
It can be disastrous, since your parent is not constructed a the time of the reference-set. The following example will demonstrate this:
#include <iostream>
using namespace std;
struct TheParent;
struct TheChild
{
TheChild(TheParent& parent);
TheParent& myParent;
};
struct TheParent
{
TheParent()
: mychild(*this)
, value(1)
{
cout << "TheParent::TheParent() : " << value << endl;
}
TheChild mychild;
int value;
};
TheChild::TheChild(TheParent& parent)
: myParent(parent)
{
cout << "TheChild::TheChild() : " << myParent.value << endl;
};
int main()
{
TheParent parent;
return 0;
}
Produces the following output, clearly noting the indeterminate state of the parent object:
TheChild::TheChild() : 1606422622
TheParent::TheParent() : 1
Bottom line: don't do it this way. You would be better served to use a dynamic child allocation instead, but even this has caveats:
#include <iostream>
using namespace std;
struct TheParent;
struct TheChild
{
TheChild(TheParent& parent);
TheParent& myParent;
};
struct TheParent
{
TheParent()
: mychild(NULL)
, value(1)
{
mychild = new TheChild(*this);
cout << "TheParent::TheParent() : " << value << endl;
}
~TheParent()
{
delete mychild;
}
TheChild* mychild;
int value;
};
TheChild::TheChild(TheParent& parent)
: myParent(parent)
{
cout << "TheChild::TheChild() : " << myParent.value << endl;
};
int main()
{
TheParent parent;
return 0;
}
This give you what you're likely hoping for:
TheChild::TheChild() : 1
TheParent::TheParent() : 1
Note, however, even this has issues if TheParent is an intermediate class in an inheritance chain, and you're desiring to access potentially overridden virtual implementations of functions in derived classes that have yet to be constructed.
Again, bottom line, if you find yourself doing this, you may want to think about why you need to in the first place.
It is bad because it is unclear how complete the parent class is at the time m_member is constructed.
For example:
class Parent
{
Parent()
: m_member(this), m_other(foo)
{ }
};
class Member
{
Member(Parent* parent)
{
std::cout << parent->m_other << std::endl; // What should this print?
}
};
A slightly better approach if a parent pointer is needed is for Member to have a 'setParent' method called in the body of the constructor.
Like the vast majority of programming practices, it is impossible to say that it is bad in general (and if you do, you are a bad person and should be ashamed). I use this sometimes, but it is uncommon; however, it is not a thing I would try to purposefully avoid by changing my class design.
Note how I used "I" a lot in the above paragraph, a sure sign this is a highly subjective issue.
I see the language as a tool to implement the solution for a given problem. By design, C++ allows explicit uses of this and other OO languages don't. Thus, I look at language features as tools in my toolbox, and every so often there is a use to bring out one tool or another.
However, and that's where coding style and practice comes in, I should know what I'm doing. I should know how to use my tools, and I should know the implications of their use. There is a defined order in which C++ initializes a new object, and as long as I work with this then I'm good. Unfortunately, some times people get lucky; other times they create bugs that way. You need to know your tools and how to use them :-)
To answer your question with my personal opinion: I try to avoid this particular construct, but on occasion I had to use it. Even pondering a class re-design wouldn't have avoided that. And so I filed this occasion under, "Ah well, sometimes my design just can't be modeled in clean-clean straight OO, the dependencies between the classes are too tight and performance matters too much."

Storing a list of arbitrary objects in C++

In Java, you can have a List of Objects. You can add objects of multiple types, then retrieve them, check their type, and perform the appropriate action for that type.
For example: (apologies if the code isn't exactly correct, I'm going from memory)
List<Object> list = new LinkedList<Object>();
list.add("Hello World!");
list.add(7);
list.add(true);
for (object o : list)
{
if (o instanceof int)
; // Do stuff if it's an int
else if (o instanceof String)
; // Do stuff if it's a string
else if (o instanceof boolean)
; // Do stuff if it's a boolean
}
What's the best way to replicate this behavior in C++?
boost::variant is similar to dirkgently's suggestion of boost::any, but supports the Visitor pattern, meaning it's easier to add type-specific code later. Also, it allocates values on the stack rather than using dynamic allocation, leading to slightly more efficient code.
EDIT: As litb points out in the comments, using variant instead of any means you can only hold values from one of a prespecified list of types. This is often a strength, though it might be a weakness in the asker's case.
Here is an example (not using the Visitor pattern though):
#include <vector>
#include <string>
#include <boost/variant.hpp>
using namespace std;
using namespace boost;
...
vector<variant<int, string, bool> > v;
for (int i = 0; i < v.size(); ++i) {
if (int* pi = get<int>(v[i])) {
// Do stuff with *pi
} else if (string* si = get<string>(v[i])) {
// Do stuff with *si
} else if (bool* bi = get<bool>(v[i])) {
// Do stuff with *bi
}
}
(And yes, you should technically use vector<T>::size_type instead of int for i's type, and you should technically use vector<T>::iterator instead anyway, but I'm trying to keep it simple.)
Your example using Boost.Variant and a visitor:
#include <string>
#include <list>
#include <boost/variant.hpp>
#include <boost/foreach.hpp>
using namespace std;
using namespace boost;
typedef variant<string, int, bool> object;
struct vis : public static_visitor<>
{
void operator() (string s) const { /* do string stuff */ }
void operator() (int i) const { /* do int stuff */ }
void operator() (bool b) const { /* do bool stuff */ }
};
int main()
{
list<object> List;
List.push_back("Hello World!");
List.push_back(7);
List.push_back(true);
BOOST_FOREACH (object& o, List) {
apply_visitor(vis(), o);
}
return 0;
}
One good thing about using this technique is that if, later on, you add another type to the variant and you forget to modify a visitor to include that type, it will not compile. You have to support every possible case. Whereas, if you use a switch or cascading if statements, it's easy to forget to make the change everywhere and introduce a bug.
C++ does not support heterogenous containers.
If you are not going to use boost the hack is to create a dummy class and have all the different classes derive from this dummy class. Create a container of your choice to hold dummy class objects and you are ready to go.
class Dummy {
virtual void whoami() = 0;
};
class Lizard : public Dummy {
virtual void whoami() { std::cout << "I'm a lizard!\n"; }
};
class Transporter : public Dummy {
virtual void whoami() { std::cout << "I'm Jason Statham!\n"; }
};
int main() {
std::list<Dummy*> hateList;
hateList.insert(new Transporter());
hateList.insert(new Lizard());
std::for_each(hateList.begin(), hateList.end(),
std::mem_fun(&Dummy::whoami));
// yes, I'm leaking memory, but that's besides the point
}
If you are going to use boost you can try boost::any. Here is an example of using boost::any.
You may find this excellent article by two leading C++ experts of interest.
Now, boost::variant is another thing to look out for as j_random_hacker mentioned. So, here's a comparison to get a fair idea of what to use.
With a boost::variant the code above would look something like this:
class Lizard {
void whoami() { std::cout << "I'm a lizard!\n"; }
};
class Transporter {
void whoami() { std::cout << "I'm Jason Statham!\n"; }
};
int main() {
std::vector< boost::variant<Lizard, Transporter> > hateList;
hateList.push_back(Lizard());
hateList.push_back(Transporter());
std::for_each(hateList.begin(), hateList.end(), std::mem_fun(&Dummy::whoami));
}
How often is that sort of thing actually useful? I've been programming in C++ for quite a few years, on different projects, and have never actually wanted a heterogenous container. It may be common in Java for some reason (I have much less Java experience), but for any given use of it in a Java project there might be a way to do something different that will work better in C++.
C++ has a heavier emphasis on type safety than Java, and this is very type-unsafe.
That said, if the objects have nothing in common, why are you storing them together?
If they do have things in common, you can make a class for them to inherit from; alternately, use boost::any. If they inherit, have virtual functions to call, or use dynamic_cast<> if you really have to.
I'd just like to point out that using dynamic type casting in order to branch based on type often hints at flaws in the architecture. Most times you can achieve the same effect using virtual functions:
class MyData
{
public:
// base classes of polymorphic types should have a virtual destructor
virtual ~MyData() {}
// hand off to protected implementation in derived classes
void DoSomething() { this->OnDoSomething(); }
protected:
// abstract, force implementation in derived classes
virtual void OnDoSomething() = 0;
};
class MyIntData : public MyData
{
protected:
// do something to int data
virtual void OnDoSomething() { ... }
private:
int data;
};
class MyComplexData : public MyData
{
protected:
// do something to Complex data
virtual void OnDoSomething() { ... }
private:
Complex data;
};
void main()
{
// alloc data objects
MyData* myData[ 2 ] =
{
new MyIntData()
, new MyComplexData()
};
// process data objects
for ( int i = 0; i < 2; ++i ) // for each data object
{
myData[ i ]->DoSomething(); // no type cast needed
}
// delete data objects
delete myData[0];
delete myData[1];
};
Sadly there is no easy way of doing this in C++. You have to create a base class yourself and derive all other classes from this class. Create a vector of base class pointers and then use dynamic_cast (which comes with its own runtime overhead) to find the actual type.
Just for completeness of this topic I want to mention that you can actually do this with pure C by using void* and then casting it into whatever it has to be (ok, my example isn't pure C since it uses vectors but that saves me some code). This will work if you know what type your objects are, or if you store a field somewhere which remembers that. You most certainly DON'T want to do this but here is an example to show that it's possible:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int a = 4;
string str = "hello";
vector<void*> list;
list.push_back( (void*) &a );
list.push_back( (void*) &str );
cout << * (int*) list[0] << "\t" << * (string*) list[1] << endl;
return 0;
}
While you cannot store primitive types in containers, you can create primitive type wrapper classes which will be similar to Java's autoboxed primitive types (in your example the primitive typed literals are actually being autoboxed); instances of which appear in C++ code (and can (almost) be used) just like primitive variables/data members.
See Object Wrappers for the Built-In Types from Data Structures and Algorithms with Object-Oriented Design Patterns in C++.
With the wrapped object you can use the c++ typeid() operator to compare the type.
I am pretty sure the following comparison will work:
if (typeid(o) == typeid(Int)) [where Int would be the wrapped class for the int primitive type, etc...]
(otherwise simply add a function to your primitive wrappers that returns a typeid and thus:
if (o.get_typeid() == typeid(Int)) ...
That being said, with respect to your example, this has code smell to me.
Unless this is the only place where you are checking the type of the object,
I would be inclined to use polymorphism (especially if you have other methods/functions specific with respect to type). In this case I would use the primitive wrappers adding an interfaced class declaring the deferred method (for doing 'do stuff') that would be implemented by each of your wrapped primitive classes. With this you would be able to use your container iterator and eliminate your if statement (again, if you only have this one comparison of type, setting up the deferred method using polymorphism just for this would be overkill).
I am a fairly inexperienced, but here's what I'd go with-
Create a base class for all classes you need to manipulate.
Write container class/ reuse container class.
(Revised after seeing other answers -My previous point was too cryptic.)
Write similar code.
I am sure a much better solution is possible. I am also sure a better explanation is possible. I've learnt that I have some bad C++ programming habits, so I've tried to convey my idea without getting into code.
I hope this helps.
Beside the fact, as most have pointed out, you can't do that, or more importantly, more than likely, you really don't want to.
Let's dismiss your example, and consider something closer to a real-life example. Specifically, some code I saw in a real open-source project. It attempted to emulate a cpu in a character array. Hence it would put into the array a one byte "op code", followed by 0, 1 or 2 bytes which could be a character, an integer, or a pointer to a string, based on the op code. To handle that, it involved a lot of bit-fiddling.
My simple solution: 4 separate stacks<>s: One for the "opcode" enum and one each for chars, ints and string. Take the next off the opcode stack, and the would take you which of the other three to get the operand.
There's a very good chance your actual problem can be handled in a similar way.
Well, you could create a base class and then create classes which inherit from it. Then, store them in a std::vector.
The short answer is... you can't.
The long answer is... you'd have to define your own new heirarchy of objects that all inherit from a base object. In Java all objects ultimately descend from "Object", which is what allows you to do this.
RTTI (Run time type info) in C++ has always been tough, especially cross-compiler.
You're best option is to use STL and define an interface in order to determine the object type:
public class IThing
{
virtual bool isA(const char* typeName);
}
void myFunc()
{
std::vector<IThing> things;
// ...
things.add(new FrogThing());
things.add(new LizardThing());
// ...
for (int i = 0; i < things.length(); i++)
{
IThing* pThing = things[i];
if (pThing->isA("lizard"))
{
// do this
}
// etc
}
}
Mike