Using a base-class object to represent its derived-class objects - c++

I need a way for a single variable to represent two kinds of objects derived from the same base class.
It's kinda hard to describe but I'll try the best:
Say the base class:
class Rectangle
{
float w;
float h;
const float area() {return w*h;}
};
And the two derived classes:
class Poker : Rectangle
{
int style; // Diamond, Club, ....
int point; // A~10, J, Q, K
};
class BusinessCard : Rectangle
{
string name;
string address;
string phone;
};
Now is it possible to declare an object, which could be either a poker or a business-card?
'cuz the usage below is illegal:
Rectangle* rec;
rec = new Poker();
delete rec;
rec = new BusinessCard();
Polymorphism might be a way but since it's only good for changing base-class' member attributes, I need this object to be able to represent exactly either of the derived objects.
EDIT:
Thanks for the all the answers. The public inheritance , the virtual destructor and even the boost::variant typedef are all fantastic hints.

You can do that. The problem is the inheritance modifier for classes is private. Most of the time, private inheritance is not what you want to use. Instead, declare it explicitly as public:
class Rectangle
{
float w;
float h;
const float area() {return w*h; }; // you missed a semicolon here, btw
virtual ~Rectangle() { } // to make `delete` work correctly
};
class Poker : public Rectangle // note the public keyword
{
int style; // Diamond, Club, ....
int point; // A~10, J, Q, K
};
class BusinessCard : public Rectangle
{
string name;
string address;
string phone;
};
Then your code snippet should work.

You need to change the qualifier for the inheritence to public.
class Poker : public Rectangle
{
int style; // Diamond, Club, ....
int point; // A~10, J, Q, K
};
class BusinessCard : public Rectangle
{
string name;
string address;
string phone;
};
is what you want. Now both classes, BusinessCard and Poker are of type Rectangle.

I need this object to be able to
represent exactly either of the
derived objects.
Don't know if I understand it correct but have a look at boost::variant
typedef boost::variant<Poker, BusinessCard> PokerOrBusinessCard
Now you can access the derived classes with a boost variant visitor class.
Maybe this can be a solution.

I think what you may be looking for is multiple inheritance, where an object can sometimes be a Poker and sometimes a BusinessCard.
See here for a tutorial:
http://www.deitel.com/articles/cplusplus_tutorials/20060225/MultipleInheritance/index.html
Note that you can decide to make it one or the other if you wish, it does not have to be both all of the time, which may satisfy what you need.

Change the subclasses to use public derivation and your code works, with some cleanup. You should also use virtual destructors so the delete works correctly.
class Rectangle
{
float w;
float h;
const float area()
{
return w*h;
}
public:
virtual ~Rectangle(){};
};
class Poker : public Rectangle
{
int style; // Diamond, Club, .... int point; // A~10, J, Q, K
};
class BusinessCard : public Rectangle
{
string name;
string address;
string phone;
};

Related

How can I store instances of related classes into a vector c++

I am having trouble finding the method to store instances of similar classes into a vector. I thought about using a base class, but I am not sure whether it will work. For example, using sports:
class player //base
{
std::string name;
int age;
player(std::string name, int age) name (name), age (age);
};
class soccerplayer: public player
{
float goal_per_game;
//etc
};
class basketballplayer: public player
{
float defensive_blocks;
float three_pointers_per_game;
//etc
};
class hockeyplayer: public player
{
//etc
};
std::vector<player> favoriteplayers;
favoriteplayers.push_back(player("Lionel Messi", 33));
I am not sure if there is a method to store the various instances of this class. If not, what workaround is possible?
You can use a vector of (smart) pointers to the base class vs. a vector of values.
std::vector<std::unique_ptr<player> > favoriteplayers;
favoriteplayers.emplace_back(new sockerplayer(...));
favoriteplayers.emplace_back(new hockeyplayer(...));
All items in the vector point to the player base-class, but they can actually be objects of derived classes.

C++: Multidimensional Array of different types

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;
}
};

Derived class inherited getter, can't find a way to return the correct value

I'm trying to have the derived class (Hero) inherit the code for a getter function from the base class (Entity). However, I can't find out how to access Hero's private variables (the correct values) through this getter.
I'm planning on assigning similar getters (about 10 total) to the Hero class as well as another derived class (Enemy). While I can technically write out each getter for the two classes, I rather limit code duplication. Is there anyway I can write the code in Entity and have the two derived classes inherit it?
#include <iostream>
using namespace std;
class Entity{
public:
Entity() {
this->speed = 0;
}
short getSpeed() {
return this->speed;
}
private:
string name;
short speed;
};
class Hero : public Entity{
public:
Hero(short speed) {
this->speed = speed;
}
private:
short speed;
};
int main()
{
Hero hero1(2);
cout << hero1.getSpeed() << endl;
return 0;
}
The output gives me 0, which is the default value of entity. Is there any way to access the hero1 value of 2 and output it?
Why would you want a method of the base return a value that is private to derived? Thats not something that you usually do.
Step back and think what you actually want to achieve. If every Enitity has a speed member and if every Hero is an Entity then Hero needs no private speed in addition.
Instead Hero should initialize its Entity part in the constructor:
class Entity{
public:
Entity(short speed = 0) : speed(speed) {} // <- fixed constructor
short getSpeed() { return speed; }
void setSpeed(short s) { speed = s; }
private:
short speed;
};
class Hero : public Entity{
public:
Hero(short speed) : Entity(speed) {}
};
I changed Entitys constructor such that you can pass an initial value for speed. Then Heros constructor can properly initialize its Entity subobject.
Is there any way to access the hero1 value of 2 and output it?
If you really want speed to be a private member of Hero then you should implement the getter in Hero also, just as you did it for Entity. However, having a speed in both classes and a getter for both is kinda weird. Choose whether speed belongs to Entity or to Hero, very unlikely you need it in both.
One question you should have answered before writing code is: Who is reponsible for what?
In the above example Entity is responsible for managing its speed. We can turn this around by saying: Entity only needs a way to retrieve the speed. How this is actually done is buisness of the subclasses (think of wooden chair vs elven archer wearing boots of speed +5). In code that would be
struct Entity{
virtual short getSpeed() { return 0; }
};
I cannot explain better than others did already, so I quote from cppreference:
Virtual functions are member functions whose behavior can be
overridden in derived classes. As opposed to non-virtual functions,
the overridden behavior is preserved even if there is no compile-time
information about the actual type of the class. If a derived class is
handled using pointer or reference to the base class, a call to an
overridden virtual function would invoke the behavior defined in the
derived class. [...]
TL;DR: virtual enables dynamic dispatch with pointers and references. It encourages subclasses to override the method with their own implementation.
Now subclasses can either be fine with the default implementation (wooden chair) or provide their own:
struct ElvenArcher : Entity {
bool hasBootsOfSpeed = true;
short baseSpeed = 10;
short getSpeed() override {
return hasBootsOfSpeed ? (baseSpeed+5) : baseSpeed;
}
};
Here override declares that the method overrides one in a base class.
PS: Note that I put the important part in bold. It is not clear from your question what would be the correct way to write your code and this answer was mainly born from a comment that was too long for a comment. I tried to outline two extremes. What you actually need is probably somewhere in between.
You need to implement getSpeed in the hero class since speed is a private variable
Here is your corrected code:
#include <iostream>
using namespace std;
class Entity{
public:
Entity() {
this->speed = 0;
}
short getSpeed() {
return this->speed;
}
private:
string name;
short speed;
};
class Hero : public Entity{
public:
Hero(short speed) {
this->speed = speed;
}
short getSpeed() {
return this->speed;
}
private:
short speed;
};
int main()
{
Hero hero1(2);
cout << hero1.getSpeed() << endl;
return 0;
}
Probably it is better to use protected instead
#include <iostream>
using namespace std;
class Entity{
public:
Entity() {
this->speed = 0;
}
short getSpeed() {
return this->speed;
}
protected:
string name;
short speed;
};
class Hero : public Entity{
public:
Hero(short speed) {
this->speed = speed;
}
};
int main()
{
Hero hero1(2);
cout << hero1.getSpeed() << endl;
return 0;
}

Appending to polymorphic list in C++?

I am new to C++ and trying to make list polymorphic/accepting anything deriving from a base class. The issue is that this list must be private, using separate methods to append and interrogate it.
After some research, I was able to get close in a safe manner through smart pointers.
Here is what I have arrived at:
class Shape
{
public:
Shape(std::string name)
{
this->name = name;
}
std::string name;
std::string getName(void)
{
return this->name;
}
};
class ShapeCollector
{
public:
void addShape(Shape shape)
{
this->shapes.push_back(std::make_unique<Shape>("hey"));
}
private:
std::vector <std::unique_ptr<Shape>> shapes;
};
I would like to be able to replace the make_unique call with the shape parameter, however nothing I try seems to play correctly.
I could create each derived class inside ShapeCollector, mirroring the constructor arguments as parameters, but this feels very counter intuitive.
Any help would be appreciated!
Write addShape to take the derived class as a template parameter:
template<class Derived, class... Args>
void addShape(Args&&... args) {
// std::forward will correctly choose when to copy or move
std::unique_ptr<Shape> shape (new Derived(std::forward<Args>(args)...));
shapes.push_back(std::move(shape));
}
This will allow you to give addShape the arguments for the derived classs constructor. For example, if we have aCircle` class:
class Circle : public Shape {
double radius;
double x;
double y;
public:
Circle(double radius, double x, double y)
: Shape("circle"), radius(radius), x(x), y(y)
{}
};
Adding it is simple:
ShapeCollector shapes;
shapes.addShape<Circle>(10.0, 0.0, 0.0);

example how to do multiple inherit?

Can somebody give me a example: How do i multiple inherit int, float from first class and char, string from second class into the third class ?
class A
{
private:
int i;
float f;
};
class B
{
private:
char c;
std::string s;
};
class C : public A, public B
{
};
Objects of type C now contain members i, f, c, and s. Note that you won't be able to access these members from within methods of C, since they remain private to A and B respectively. In order to access these from within C methods, they would have to have been originally declared as public or protected rather than private, but that is not good design.
Normally, you don't use multiple inheritance to get access to data (data should normally be private, so a derived class can't access it anyway).
Multiple inheritance basically produces an object with more than one set of properties. For example, consider doors, some wood and some steel:
class steel {
unsigned int AISI_number;
char Rockwell_scale;
unsigned int Rockwell_number;
};
class wood {
double density;
std::string species;
};
class door {
int width;
int height;
unsigned char num_hinges;
};
class wooden_door : public wood, public door {};
class steel_door : public steel, public door {};
This is a bit contrived, because it's probably pretty rare that we'd actually care much about the steel in a steel door (e.g., that it's 1020 steel that has been hardened to Rockwell C40), but I hope the general idea comes through anyway. [And yes, I'm aware that all the data is inaccessible, because it's all private, and there's no code to access it in any of the classes...]
Do you mean inheriting from a class with int and float field and a second class containing a char and string field?
class1
{
int anInt;
float aFloat;
}
class2
{
char aChar;
string aString;
}
class3 : public class1, public clas2
{
...
}
1) You cannon inherit from base
types.
2) Normal multiple
inheritance looks like this:
class A { /* ... */ };
class B { /* ... */ };
class C { /* ... */ };
class X : public A, private B, public C { /* ... */ };