C++: Multidimensional Array of different types - c++

I am just starting to practice some C++ and a cool project i picked up (maybe too ambitious) is to build a Ecosystem Simulator. Basically i want to have a world of Plants, Rabbits and Foxes. Rabbits eat plants and Foxes eat Rabbits. I was thinking of having different classes just like this:
struct pos{
int x;
int y;
};
class Plant{
pos posit;
int growrate;
bool alive;
};
class Rabbit {
pos posit;
int age;
int speed;
int viewradius;
//other stuff
public:
Rabbit(pos,int,int);
void move();
void eat(Plant);
void die();
Rabbit mate(Rabbit);
};
class Fox{
//other stuff here
};
I want to have a 2D Array in which every element can be a Fox, a Rabbit, a Plant or a Plant with a Rabbit on. How can i do that? Is there an easy way?

As a first order approximation, you could define a structure with three optionals.
struct Square {
std::optional<Plant> plant;
std::optional<Rabbit> rabbit;
std::optional<Fox> fox;
};
This structure now can hold one of the three or both a plant and rabbit. It also allows for invalid combinations, but this is the simplest representation of what you asked.
For the 2-dimensional array, you could use a sparse representation using nested maps, if an actual array is not required.
typedef std::map<int, std::map<int, Square>> Grid;
Alternatively, you could map a pos directly to a Square.

Many possible/valid ways to design this. I'd do something like this:
struct Rabbit {};
struct Fox {};
struct Plant {};
struct Cell {
std::shared_ptr<Rabbit> rabbit;
std::shared_ptr<Fox> fox;
std::shared_ptr<Plant> plant;
bool hasRabbit() const { return !!rabbit; }
bool hasFox() const { return !!fox; }
bool hasPlant() const { return !!plant; }
};
using Grid = std::array<std::array<Cell, 100>, 100>;
int main()
{
Grid grid;
grid[2][3].rabbit = std::make_shared<Rabbit>();
grid[2][3].plant = std::make_shared<Plant>();
Cell& cell2_3 = grid[2][3];
if (cell2_3.hasRabbit() && cell2_3.hasPlant()) {
// Eat plant
cell2_3.rabbit->eat(cell2_3.plant);
cell2_3.plant.reset();
}
}

I would strongly prefer the combination of std::variant & std::visit. Since your classes are concrete types and exposes non polymorphic behavior, I suggest not using a polymorphic class hierarchy: you could hardly bubble up all classes member functions into pure virtual functions in an abstract base class (let's say Animal). For example, there would be no sensible overriding implementation for void eat(Plant) in the class Plant. Also if you choose not to pull member functions as pure virtual functions into an abstract base class (Animal), then any useful operation on the base class would require overusing of dynamic downcast, which is against good programming practices; see ES.48: Avoid casts from the cppcoreguidelines.
std::variant is implemented as a tagged union, so it makes it possible to initialize and assign it from an object of different alternative types at runtime. For example, you could define using Animal = std::variant<Plant, Rabbit, Fox>;. Now, when you use a variant object, you normally want to execute different operations depending of the type of the object contained in the variant. The canonical way to do this is by using std::visit which takes as first parameter a visitor (a function object with with overloaded operators() for each types of the variant), and the second parameter is the variant. Also, as an advice, pass your parameters by reference. Otherwise calling Rabbit::eat(plant) will make the rabbit eat a copy of the plant and not the plant itself. Try the following minimal working example (I used gcc10.2 with cpp17 flag), I chose to define an EatingVisitor but you can define as many visitors as you want:
#include <iostream>
#include <variant>
struct pos{
int x;
int y;
};
class Plant{
pos posit;
int growrate;
bool alive;
};
class Rabbit {
pos posit;
int age;
int speed;
int viewradius;
//other stuff
public:
Rabbit() = default;
Rabbit(pos,int,int);
void move();
void eat(Plant&) { std::cout << "rabbit eat plant\n"; }
void die();
Rabbit mate(Rabbit&);
};
class Fox{
public:
void eat(Rabbit&) { std::cout << "fox eat rabbit\n"; }//other stuff here
};
using Animal = std::variant<Plant, Fox, Rabbit>;
struct EatingVisitor
{
Animal& animal;
void operator()(Rabbit& rab) const {
if (auto pplant = std::get_if<Plant>(&animal))
rab.eat(*pplant);
}
void operator()(Plant& rab) const {
// noop
}
void operator()(Fox& fox) const {
if (auto prab = std::get_if<Rabbit>(&animal))
fox.eat(*prab);
}
};
int main()
{
// The animal that is going to be eaten
Animal plan = Plant{};
// The eating animal
Animal rab = Rabbit{};
// The eating function object
EatingVisitor vis{plan};
// rab eats the animal referred to by vis
std::visit(vis, rab);
}
Also, a Plant with a Rabbit on it should be a relation between a Plant and a Rabbit, not a type by itself. There are different ways to express this but a possible implementation could be:
class Rabbit
{
void hop_on(Plant& plant) {
this->move(plant.position());
plant.host(this)
}
};
class Plant
{
void host(Rabbit* rab) {
this->host_rabbit = rab;
}
};

Related

Do I need to initiate parent class or just child class

I am new in programing and I am analyzing code with parent class fruit and child classes apple and pear. In this example there is pointer to parent class. After I extended this code I find out that using object I can access parent public members and all child members. Question is why do I need those pointers?
// are this pointer needed since I can use j.setWeight(11)
#include <iostream>
using namespace std;
class fruit {
private:
int weight;
public:
void setWeight(int x)
{
weight = x;
}
int getWeight()
{
return weight;
}
};
class apple : public fruit {
public:
void eat()
{
cout << "Now I am eating apple"
<< "=" << getWeight() << endl;
}
};
class pear : public fruit {
public:
void eat()
{
cout << "Now I am eating pear"
<< " = " << getWeight() << endl;
}
};
int main()
{
apple j;
pear k;
fruit* fruit1 = &j;
fruit* fruit2 = &k;
k.setWeight(5);
k.eat();
fruit1->setWeight(11);
apple apple;
apple.postaviTezinu(16);
apple.jelo();
return 0;
}
are this pointers needed since I can use j.setWeight(11) and results is same as
fruit1 -> setWeight(11) ... what s difference, thx
I suspect that the code you are looking at was written to demonstrate how pointers to base classes can be used with objects of derived classes. No, pointers are not necessary for the functionality of this learning exercise. In fact, that is probably the reason this functionality was chosen. Since you see how to accomplish the same thing without pointers, it should be easier for you to relate pointers to what you already know.
The key learning points I see in this exercise are
The same pointer type (fruit *) can point to objects of different types (apple or pear).
When using the pointer to the base class, you can access base class members.
When using the pointer to the base class, you cannot access derived class members. (Implied by omission; compare what is done with k to what is done with fruit1.)
You will need to move on to the more advanced lessons to learn when pointers are more useful than accessing objects directly (probably after eat() is turned into a virtual function). For now, just learn how the same task can be accomplished by different means.
(Sure, you could get that information here, but that code looks like it's part of a series. Continuing with that series might be the better way to learn.)
Since you're new to programming, learning polymorphism may be a bit advanced for you at this stage. To answer your question directly: No, you don't need pointers in your example code, and they are in no way helpful.
However, pointers to objects are often useful for:
Reducing unnecessary copying of objects
In the case of polymorphism (as in your example) pointers help in sections of your programme where you don't know which object type you're dealing with, or don't want to have to deal with them in different ways
Example:
#include <iostream>
#include <vector>
class A
{
public:
virtual void foo ()
{
std::cout << " I am A\n";
}
};
class B : public A
{
public:
virtual void foo ()
{
std::cout << " I am B\n";
}
};
void bar ( const std::vector <A*> & obj )
{
// Here it outputs the foo () function that is
// appropriate for the class
for ( unsigned int i = 0; i < obj . size (); ++i )
obj [i] -> foo ();
}
int main ()
{
A a1, a2, a3;
B b1, b2, b3;
// the below input style requires C++11,
// otherwise input them one-by-one
std::vector <A*> array {&a1, &b1, &a2, &a3, &b2, &b3};
bar ( array );
return 0;
}
The above array can store any A objects, including the inherited objects (it can't do this without pointers); and the bar function can still perform operations on the elements in the array without needing to know which object type they belong to within the inheritance tree (due to the virtual function). This is crucial for taking advantage of polymorphism, and saving on repetition of functions and code in general.

Am I Abusing Inheritance Here? What's A Best-Practice Alternative/Pattern?

BIG EDIT
So after gathering some feedback from all of you, and meditating on the XY problem as Zack suggested, I decided to add another code example which illustrates exactly what I'm trying to accomplish (ie the "X") instead of asking about my "Y".
So now we are working with cars and I've added 5 abstract classes: ICar, ICarFeatures, ICarParts, ICarMaker, ICarFixer. All of these interfaces will wrap or use a technology-specific complex object provided by a 3rd party library, depending on the derived class behind the interface. These interfaces will intelligently manage the life cycle of the complex library objects.
My use case here is the FordCar class. In this example, I used the Ford library to access classes FordFeatureImpl, FordPartsImpl, and FordCarImpl. Here is the code:
class ICar {
public:
ICar(void) {}
virtual ~ICar(void) {}
};
class FordCar : public ICar {
public:
ICar(void) {}
~FordCar(void) {}
FordCarImpl* _carImpl;
};
class ICarFeatures {
public:
ICarFeatures(void) {}
virtual ~ICarFeatures(void) {}
virtual void addFeature(UserInput feature) = 0;
};
class FordCarFeatures : public ICarFeatures{
public:
FordCarFeatures(void) {}
virtual ~FordCarFeatures(void) {}
virtual void addFeature(UserInput feature){
//extract useful information out of feature, ie:
std::string name = feature.name;
int value = feature.value;
_fordFeature->specialAddFeatureMethod(name, value);
}
FordFeatureImpl* _fordFeature;
};
class ICarParts {
public:
ICarParts(void) {}
virtual ~ICarParts(void) {}
virtual void addPart(UserInput part) = 0;
};
class FordCarParts :public ICarParts{
public:
FordCarParts(void) {}
virtual ~FordCarParts(void) {}
virtual void addPart(UserInput part) {
//extract useful information out of part, ie:
std::string name = part.name;
std::string dimensions = part.dimensions;
_fordParts->specialAddPartMethod(name, dimensions);
}
FordPartsImpl* _fordParts;
};
class ICarMaker {
public:
ICarMaker(void) {}
virtual ~ICarMaker(void) {}
virtual ICar* makeCar(ICarFeatures* features, ICarParts* parts) = 0;
};
class FordCarMaker {
public:
FordCarMaker(void) {}
virtual ~FordCarMaker(void) {}
virtual ICar* makeCar(ICarFeatures* features, ICarParts* parts){
FordFeatureImpl* fordFeatures = dynamic_cast<FordFeatureImpl*>(features);
FordPartsImpl* fordParts = dynamic_cast<FordPartsImpl*>(parts);
FordCar* fordCar = customFordMakerFunction(fordFeatures, fordParts);
return dynamic_cast<ICar*>(fordCar);
}
FordCar* customFordMakerFunction(FordFeatureImpl* fordFeatures, FordPartsImpl* fordParts) {
FordCar* fordCar = new FordCar;
fordCar->_carImpl->specialFeatureMethod(fordFeatures);
fordCar->_carImpl->specialPartsMethod(fordParts);
return fordCar;
}
};
class ICarFixer {
public:
ICarFixer(void) {}
virtual ~ICarFixer(void) {}
virtual void fixCar(ICar* car, ICarParts* parts) = 0;
};
class FordCarFixer {
public:
FordCarFixer(void) {}
virtual ~FordCarFixer(void) {}
virtual void fixCar(ICar* car, ICarParts* parts) {
FordCar* fordCar = dynamic_cast<FordCar*>(car);
FordPartsImpl* fordParts = dynamic_cast<FordPartsImpl*>(parts);
customFordFixerFunction(fordCar, fordParts);
}
customFordFixerFunction(FordCar* fordCar, FordPartsImpl* fordParts){
fordCar->_carImpl->specialRepairMethod(fordParts);
}
};
Notice that I must use dynamic casting to access the technology-specific objects within the abstract interfaces. This is what makes me think I'm abusing inheritance and provoked me to ask this question originally.
Here is my ultimate goal:
UserInput userInput = getUserInput(); //just a configuration file ie XML/YAML
CarType carType = userInput.getCarType();
ICarParts* carParts = CarPartFactory::makeFrom(carType);
carParts->addPart(userInput);
ICarFeatures* carFeatures = CarFeaturesFactory::makeFrom(carType);
carFeatures->addFeature(userInput);
ICarMaker* carMaker = CarMakerFactory::makeFrom(carType);
ICar* car = carMaker->makeCar(carFeatures, carParts);
UserInput repairSpecs = getUserInput();
ICarParts* replacementParts = CarPartFactory::makeFrom(carType);
replacementParts->addPart(repairSpecs);
ICarFixer* carFixer = CarFixerFactory::makeFrom(carType);
carFixer->fixCar(car, replacementParts);
Perhaps now you all have a better understanding of what I'm trying to do and perhaps where I can improve.
I'm trying to use pointers of base classes to represent derived (ie Ford) classes, but the derived classes contain specific objects (ie FordPartsImpl) which are required by the other derived classes (ie FordCarFixer needs a FordCar and FordPartsImpl object). This requires me to use dynamic casting to downcast a pointer from the base to its respective derived class so I can access these specific Ford objects.
My question is: am I abusing inheritance here? I'm trying to have a many-to-many relationship between the workers and objects. I feel like I'm doing something wrong by having an Object family of class which literally do nothing but hold data and making the ObjectWorker class have to dynamic_cast the object to access the insides.
That is not abusing inheritance... This is abusing inheritance
class CSNode:public CNode, public IMvcSubject, public CBaseLink,
public CBaseVarObserver,public CBaseDataExchange, public CBaseVarOwner
Of which those who have a C prefix have huge implementations
Not only that... the Header is over 300 lines of declarations.
So no... you are not abusing inheritance right now.
But this class I just showed you is the product of erosion. I'm sure the Node as it began it was a shinning beacon of light and polymorphism, able to switch smartly between behavior and nodes.
Now it has become a Kraken, a Megamoth, Cthulu itself trying to chew my insides with only a vision of it.
Heed this free man, heed my counsel, beware of what your polymorphism may become.
Otherwise it is fine, a fine use of inheritance of something I suppose is an Architecture in diapers.
What other alternatives do I have if I want to only have a single work() method?
Single Work Method... You could try:
Policy Based Design, where a policy has the implementation of your model
A Function "work" that it is used by every single class
A Functor! Instantiated in every class that it will be used
But your inheritance seems right, a single method that everyone will be using.
One more thing....I'm just gonna leave this wiki link right here
Or maybe just copy paste the wiki C++ code... which is very similar to yours:
#include <iostream>
#include <string>
template <typename OutputPolicy, typename LanguagePolicy>
class HelloWorld : private OutputPolicy, private LanguagePolicy
{
using OutputPolicy::print;
using LanguagePolicy::message;
public:
// Behaviour method
void run() const
{
// Two policy methods
print(message());
}
};
class OutputPolicyWriteToCout
{
protected:
template<typename MessageType>
void print(MessageType const &message) const
{
std::cout << message << std::endl;
}
};
class LanguagePolicyEnglish
{
protected:
std::string message() const
{
return "Hello, World!";
}
};
class LanguagePolicyGerman
{
protected:
std::string message() const
{
return "Hallo Welt!";
}
};
int main()
{
/* Example 1 */
typedef HelloWorld<OutputPolicyWriteToCout, LanguagePolicyEnglish> HelloWorldEnglish;
HelloWorldEnglish hello_world;
hello_world.run(); // prints "Hello, World!"
/* Example 2
* Does the same, but uses another language policy */
typedef HelloWorld<OutputPolicyWriteToCout, LanguagePolicyGerman> HelloWorldGerman;
HelloWorldGerman hello_world2;
hello_world2.run(); // prints "Hallo Welt!"
}
More important questions are
How are you going to use an Int Object with your StringWorker?
You current implementation won't be able to handle that
With policies it is possible.
What are the possible objects?
Helps you define if you need this kind of behavior
And remember, don't kill a chicken with a shotgun
Maybe your model will never really change overtime.
You have committed a design error, but it is not "abuse of inheritance". Your error is that you are trying to be too generic. Meditate upon the principle of You Aren't Gonna Need It. Then, think about what you actually have. You don't have Objects, you have Dogs, Cats, and Horses. Or perhaps you have Squares, Polygons, and Lines. Or TextInEnglish and TextInArabic. Or ... the point is, you probably have a relatively small number of concrete things and they probably all go in the same superordinate category. Similarly, you do not have Workers. On the assumption that what you have is Dogs, Cats, and Horses, then you probably also have an Exerciser and a Groomer and a Veterinarian.
Think about your concrete problem in concrete terms. Implement only the classes and only the relationships that you actually need.
The point is that you're not accessing the specific functionality through the interfaces. The whole reason for using interfaces is that you want all Cars to be made, fixed and featured ... If you're not going to use them in that way, don't use interfaces (and inheritance) at all, but simply check at user input time which car was chosen and instantiate the correct specialized objects.
I've changed your code a bit so that only at "car making" time there will be an upward dynamic_cast. I would have to know all the things you want to do exactly to create interfaces I would be really happy with.
class ICar {
public:
ICar(void) {}
virtual ~ICar(void) {}
virtual void specialFeatureMethod(ICarFeatures *specialFeatures);
virtual void specialPartsMethod(ICarParts *specialParts);
virtual void specialRepairMethod(ICarParts *specialParts);
};
class FordCar : public ICar {
public:
FordCar(void) {}
~FordCar(void) {}
void specialFeatureMethod(ICarFeatures *specialFeatures) {
//Access the specialFeatures through the interface
//Do your specific Ford stuff
}
void specialPartsMethod(ICarParts *specialParts) {
//Access the specialParts through the interface
//Do your specific Ford stuff
}
void specialRepairMethod(ICarParts *specialParts) {
//Access the specialParts through the interface
//Do your specific Ford stuff
}
};
class ICarFeatures {
public:
ICarFeatures(void) {}
virtual ~ICarFeatures(void) {}
virtual void addFeature(UserInput feature) = 0;
};
class FordCarFeatures : public ICarFeatures{
public:
FordCarFeatures(void) {}
~FordCarFeatures(void) {}
void addFeature(UserInput feature){
//extract useful information out of feature, ie:
std::string name = feature.name;
int value = feature.value;
_fordFeature->specialAddFeatureMethod(name, value);
}
FordFeatureImpl* _fordFeature;
};
class ICarParts {
public:
ICarParts(void) {}
virtual ~ICarParts(void) {}
virtual void addPart(UserInput part) = 0;
};
class FordCarParts :public ICarParts{
public:
FordCarParts(void) {}
~FordCarParts(void) {}
void addPart(UserInput part) {
//extract useful information out of part, ie:
std::string name = part.name;
std::string dimensions = part.dimensions;
_fordParts->specialAddPartMethod(name, dimensions);
}
FordPartsImpl* _fordParts;
};
class ICarMaker {
public:
ICarMaker(void) {}
virtual ~ICarMaker(void) {}
virtual ICar* makeCar(ICarFeatures* features, ICarParts* parts) = 0;
};
class FordCarMaker {
public:
FordCarMaker(void) {}
~FordCarMaker(void) {}
ICar* makeCar(ICarFeatures* features, ICarParts* parts){
return customFordMakerFunction(features, parts);
}
ICar* customFordMakerFunction(ICarFeatures* features, ICarParts* parts) {
FordCar* fordCar = new FordCar;
fordCar->specialFeatureMethod(features);
fordCar->specialPartsMethod(parts);
return dynamic_cast<ICar*>(fordCar);
}
};
class ICarFixer {
public:
ICarFixer(void) {}
virtual ~ICarFixer(void) {}
virtual void fixCar(ICar* car, ICarParts* parts) = 0;
};
class FordCarFixer {
public:
FordCarFixer(void) {}
~FordCarFixer(void) {}
void fixCar(ICar* car, ICarParts* parts) {
customFordFixerFunction(car, parts);
}
void customFordFixerFunction(ICar* fordCar, ICarParts *fordParts){
fordCar->specialRepairMethod(fordParts);
}
};
One can do better (for certain values of "better"), with increased complexity.
What is actually being done here? Let's look point by point:
There's some object type, unknown statically, determined at run time from a string
There's some worker type, also unknown statically, determined at run time from another string
Hopefully the object type and the worker type will match
We can try to turn "hopefully" into "certainly" with some template code.
ObjectWorkerDispatcher* owd =
myDispatcherFactory->create("someWorker", "someObject");
owd->dispatch();
Obviously both object and worker are hidden in the dispatcher, which is completely generic:
class ObjectWorkerDispatcher {
ObjectWorkerDispatcher(string objectType, string workerType) { ... }
virtual void dispatch() = 0;
}
template <typename ObjectType>
class ConcreteObjectWorkerDispatcher : public ObjectWorkerDispatcher {
void dispatch () {
ObjectFactory<ObjectType>* of = findObjectFactory(objectTypeString);
WorkerFactory<ObjectType>* wf = findWorkerFactory(workerTypeString);
ObjectType* obj = of->create();
Worker<ObjectType>* wrk = wf->create();
wrk->doWork(obj);
}
map<string, ObjectFactory<ObjectType>*> objectFactories;
map<string, WorkerFactory<ObjectType>*> workerFactories;
ObjectFactory<ObjectType>* findObjectFactory(string) { .. use map }
WorkerFactory<ObjectType>* findWorkerFactory(string) { .. use map }
}
We have different unrelated types of Object. No common Object class, but we can have e.g. several subtypes of StringObject, all compatible with all kinds of StringWorker.
We have an abstract Worker<ObjectType> class template and concrete MyStringWorker : public Worker<StringObject> , OtherStringWorker : public Worker<StringObject> ... classes.
Both kinds of factories are inheritance-free. Different types of factories are kept completely separate (in different dispatchers) and never mix.
There's still some amount of blanks to fill in, but hopefully it all should be more or less clear.
No casts are used in making of this design. You decide whether this property alone is worth such an increase in complexity.
I think you have the right solution per your needs. One thing I see that can be improved is removing the use of carType from the function that deals with the objects at the base class level.
ICar* FordCarFixer::getFixedCar(UserInput& userInput)
{
FordCarParts* carParts = new FordPartFactory;
carParts->addPart(userInput);
FordCarFeatures* carFeatures = new FordCarFeatures;
carFeatures->addFeature(userInput);
FordCarMaker* carMaker = new FordCarMaker;
FordCar* car = carMaker->makeCar(carFeatures, carParts);
UserInput repairSpecs = getUserInput();
ForCarParts* replacementParts = new ForCarParts;
replacementParts->addPart(repairSpecs);
FordCarFixer* carFixer = new FordCarFixer;
carFixer->fixCar(car, replacementParts);
return car;
}
UserInput userInput = getUserInput();
ICar* car = CarFixerFactory::getFixedCar(userInput);
With this approach, most of the objects at FordCarFixer level are Ford-specific.

Overwrite Base Class Member with New Type

I'm trying to use C++ to emulate something like dynamic typing. I'm approaching the problem with inherited classes. For example, a function could be defined as
BaseClass* myFunction(int what) {
if (what == 1) {
return new DerivedClass1();
} else if (what == 2) {
return new DerivedClass2();
}
}
The base class and each derived class would have the same members, but of different types. For example, BaseClass may have int xyz = 0 (denoting nothing), DerivedClass1 might have double xyz = 123.456, and DerivedClass2 might have bool xyz = true. Then, I could create functions that returned one type but in reality returned several different types. The problem is, when ere I try to do this, I always access the base class's version of xyz. I've tried using pointers (void* for the base, and "correct" ones for the derived classes), but then every time I want to access the member, I have to do something like *(double*)(obj->xyz) which ends up being very messy and unreadable.
Here's an outline of my code:
#include <iostream>
using std::cout;
using std::endl;
class Foo {
public:
Foo() {};
void* member;
};
class Bar : public Foo {
public:
Bar() {
member = new double(123.456); // Make member a double
};
};
int main(int argc, char* args[]) {
Foo* obj = new Bar;
cout << *(double*)(obj->member);
return 0;
};
I guess what I'm trying to ask is, is this "good" coding practice? If not, is there a different approach to functions that return multiple types or accept multiple types?
That is not actually the way to do it.
There are two typical ways to implement something akin to dynamic typing in C++:
the Object-Oriented way: a class hierarchy and the Visitor pattern
the Functional-Programming way: a tagged union
The latter is rather simple using boost::variant, the former is well documented on the web. I would personally recommend boost::variant to start with.
If you want to go down the full dynamic typing road, then things get trickier. In dynamic typing, an object is generally represented as a dictionary containing both other objects and functions, and a function takes a list/dictionary of objects and returns a list/dictionary of objects. Modelling it in C++ is feasible, but it'll be wordy...
How is an object represented in a dynamically typed language ?
The more generic representation is for the language to represent an object as both a set of values (usually named) and a set of methods (named as well). A simplified representation looks like:
struct Object {
using ObjectPtr = std::shared_ptr<Object>;
using ObjectList = std::vector<ObjectPtr>;
using Method = std::function<ObjectList(ObjectList const&)>;
std::map<std::string, ObjectPtr> values;
std::map<std::string, Method> methods;
};
If we take Python as an example, we realize we are missing a couple things:
We cannot implement getattr for example, because ObjectPtr is a different type from Method
This is a recursive implementation, but without the basis: we are lacking innate types (typically Bool, Integer, String, ...)
Dealing with the first issue is relatively easy, we transform our object to be able to become callable:
class Object {
public:
using ObjectPtr = std::shared_ptr<Object>;
using ObjectList = std::vector<ObjectPtr>;
using Method = std::function<ObjectList(ObjectList const&)>;
virtual ~Object() {}
//
// Attributes
//
virtual bool hasattr(std::string const& name) {
throw std::runtime_error("hasattr not implemented");
}
virtual ObjectPtr getattr(std::string const&) {
throw std::runtime_error("gettattr not implemented");
}
virtual void setattr(std::string const&, ObjectPtr) {
throw std::runtime_error("settattr not implemented");
}
//
// Callable
//
virtual ObjectList call(ObjectList const&) {
throw std::runtime_error("call not implemented");
}
virtual void setcall(Method) {
throw std::runtime_error("setcall not implemented");
}
}; // class Object
class GenericObject: public Object {
public:
//
// Attributes
//
virtual bool hasattr(std::string const& name) override {
return values.count(name) > 0;
}
virtual ObjectPtr getattr(std::string const& name) override {
auto const it = values.find(name);
if (it == values.end) {
throw std::runtime_error("Unknown attribute");
}
return it->second;
}
virtual void setattr(std::string const& name, ObjectPtr object) override {
values[name] = std::move(object);
}
//
// Callable
//
virtual ObjectList call(ObjectList const& arguments) override {
if (not method) { throw std::runtime_error("call not implemented"); }
return method(arguments);
}
virtual void setcall(Method m) {
method = std::move(m);
}
private:
std::map<std::string, ObjectPtr> values;
Method method;
}; // class GenericObject
And dealing with the second issue requires seeding the recursion:
class BoolObject final: public Object {
public:
static BoolObject const True = BoolObject{true};
static BoolObject const False = BoolObject{false};
bool value;
}; // class BoolObject
class IntegerObject final: public Object {
public:
int value;
}; // class IntegerObject
class StringObject final: public Object {
public:
std::string value;
}; // class StringObject
And now you need to add capabilities, such as value comparison.
You can try the following design:
#include <iostream>
using std::cout;
using std::endl;
template<typename T>
class Foo {
public:
Foo() {};
virtual T& member() = 0;
};
class Bar : public Foo<double> {
public:
Bar() : member_(123.456) {
};
virtual double& member() { return member_; }
private:
double member_;
};
int main(int argc, char* args[]) {
Foo<double>* obj = new Bar;
cout << obj->member();
return 0;
};
But as a consequence the Foo class already needs to be specialized and isn't a container for any type anymore.
Other ways to do so, are e.g. using a boost::any in the base class
If you need a dynamic solution you should stick to using void* and size or boost::any. Also you need to pass around some type information as integer code or string so that you can decode the actual type of the content.
See also property design pattern.
For example, you can have a look at zeromq socket options https://github.com/zeromq/libzmq/blob/master/src/options.cpp

Calling function from derived class through base class that is not overridden

in C++;
Is there a way of calling a function from a derived class through the base class
even when the function is not overridden? In other words, I'm using a base class in
order to have heterogeneous containers without boost; I want to call a member function
that is only specific to a derived class...
Example:
(I just made this code up so there's probably a syntax error but hopefully you get the gist)
class Vehicle
{
public:
virtual void do_vehicle_stuff();
// virtual void do_car_specific_stuff(); makes no sense here
}
class Car : public Vehicle
{
public:
void do_vehicle_stuff();
void do_car_specific_stuff();
}
Car a,b;
list<Vehicle> vehicle_list;
vehicle_list.push_back(a);
vehicle_list.push_back(b);
vehicle_list.front().do_car_specific_stuff();
error: 'Class Vehicle' has no member named 'do_car_specific_stuff()'
You are slicing your classes when you insert them into the list. In
C++ subtype polymorphism (the kind of polymorphism you are using) only
works through references or pointers but not values. When you insert
your carS into the list they are converted to VehicleS.
An example:
Car c;
std::vector<Vehicle> vs;
vs.push_back(c); // slicing happens
vs.front(); // not a car anymore, but just a vehicle,
// the Car-ness is lost through the copy operation
How do to it:
std::vector<std::unique_ptr<Vehicle>> vs;
vs.push_back(new Car());
vs.front(); // actually a Car
After you have resolved that fundamental flaw of your code, this might
help you:
Vehicle* vehiclep = new Car();
if(auto carp = dynamic_cast<Car*>(vehiclep)) {
carp->do_car_specific_stuff();
}
This is a rather costly operation and usually an indication of a
design smell, so you might want to rethink what you are doing.
Here's a more appropriate design:
struct Vehicle
{
virtual ~Vehicle() { }
void do_vehicle_stuff()
{
vehicle_impl();
}
private:
virtual void vehicle_impl() = 0;
};
struct Car : Vehicle
{
private:
virtual void vehicle_impl()
{
my_vehicle_stuff();
my_car_specific_stuff();
}
void my_vehicle_stuff() { /* what you had originally */ }
void my_car_specific_stuff() { /* car-only stuff */ }
};
std::list<std::unique_ptr<Vehicle>> vehicles;
vehicles.emplace_back(new Car);
vehicles.emplace_back(new Motorcycle);
vehicles.emplace_back(new Carriage);

C++ class that can hold one of a set of classes that all inherit from a common class

What are the ways in C++ to handle a class that has ownership of an instance of another class, where that instance could potentially be of a number of classes all of which inherit from a common class?
Example:
class Item { //the common ancestor, which is never used directly
public:
int size;
}
class ItemWidget: public Item { //possible class 1
public:
int height;
int width;
}
class ItemText: public Item { //possible class 2
std::string text;
}
Let's say there is also a class Container, each of which contains a single Item, and the only time anyone is ever interested in an Item is when they are getting it out of the Container. Let's also say Items are only created at the same time the Container is created, for the purpose of putting them in the Container.
What are the different ways to structure this? We could make a pointer in Container for the contained Item, and then pass arguments to the constructor of Container for what sort of Item to call new on, and this will stick the Items all in the heap. Is there a way to store the Item in the stack with the Container, and would this have any advantages?
Does it make a difference if the Container and Items are immutable, and we know everything about them at the moment of creation, and will never change them?
A correct solution looks like:
class Container {
public:
/* ctor, accessors */
private:
std::unique_ptr<Item> item;
};
If you have an old compiler, you can use std::auto_ptr instead.
The smart pointer ensures strict ownership of the item by the container. (You could as well make it a plain pointer and roll up your own destructor/assignment op/copy ctor/move ctor/ move assignment op/ etc, but unique_ptr has it all already done, so...)
Why do you need to use a pointer here, not just a plain composition?
Because if you compose, then you must know the exact class which is going to be composed. You can't introduce polymorphism. Also the size of all Container objects must be the same, and the size of Item's derived classes may vary.
And if you desperately need to compose?
Then you need as many variants of Container as there are the items stored, since every such Container will be of different size, so it's a different class. Your best shot is:
struct IContainer {
virtual Item& getItem() = 0;
};
template<typename ItemType>
struct Container : IContainer {
virtual Item& getItem() {
return m_item;
}
private:
ItemType m_item;
};
OK, crazy idea. Don't use this:
class AutoContainer
{
char buf[CRAZY_VALUE];
Base * p;
public:
template <typename T> AutoContainer(const T & x)
: p(::new (buf) T(x))
{
static_assert(std::is_base_of<Base, T>::value, "Invalid use of AutoContainer");
static_assert(sizeof(T) <= CRAZY_VAL, "Not enough memory for derived class.");
#ifdef __GNUC__
static_assert(__has_virtual_destructor(Base), "Base must have virtual destructor!");
#endif
}
~AutoContainer() { p->~Base(); }
Base & get() { return *p; }
const Base & get() const { return *p; }
};
The container requires no dynamic allocation itself, you must only ensure that CRAZY_VALUE is big enough to hold any derived class.
the example code below compiles and shows how to do something similar to what you want to do. this is what in java would be called interfaces. see that you need at least some similarity in the classes (a common function name in this case). The virtual keyword means that all subclasses need to implement this function and whenever that function is called the function of the real class is actually called.
whether the classes are const or not doesn't harm here. but in general you should be as const correct as possible. because the compiler can generate better code if it knows what will not be changed.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class outputter {
public:
virtual void print() = 0;
};
class foo : public outputter {
public:
virtual void print() { std::cout << "foo\n"; }
};
class bar : public outputter {
public:
virtual void print() { std::cout << "bar\n"; }
};
int main(){
std::vector<outputter *> vec;
foo *f = new foo;
vec.push_back(f);
bar *b = new bar ;
vec.push_back(b);
for ( std::vector<outputter *>::iterator i =
vec.begin(); i != vec.end(); ++i )
{
(*i)->print();
}
return 0;
}
Output:
foo
bar
Hold a pointer (preferably a smart one) in the container class, and call a pure virtual clone() member function on the Item class that is implemented by the derived classes when you need to copy. You can do this in a completely generic way, thus:
class Item {
// ...
private:
virtual Item* clone() const = 0;
friend Container; // Or make clone() public.
};
template <class I>
class ItemCloneMixin : public Item {
private:
I* clone() const { return new I(static_cast<const I&>(*this); }
};
class ItemWidget : public ItemCloneMixin<ItemWidget> { /* ... */ };
class ItemText : public ItemCloneMixin<ItemText> { /* ... */ };
Regarding stack storage, you can use an overloaded new that calls alloca(), but do so at your peril. It will only work if the compiler inlines your special new operator, which you can't force it to do (except with non-portable compiler pragmas). My advice is that it just isn't worth the aggravation; runtime polymorphism belongs on the heap.