Creating array of different objects - c++

I have this code, but I don't see where I went wrong here. It seem to compile OK but I cannot access Computer or Appliance functions. Can someone please help me understand how can I make an array that holds different objects on this code example I have here?
#include <iostream>
using namespace std;
class Technics
{
private:
int price, warranty;
static int objCount;
double pvn;
char *name, *manufacturer;
public:
Technics()
{
this->objCount++;
};
Technics(int price)
{
this->objCount++;
this->price = price;
}
~Technics(){
this->objCount = this->objCount - 2;
};
static int getObjCount()
{
return objCount;
}
void setPrice(int price)
{
this->price = price;
}
int getPrice()
{
return this->price;
}
void resetCount()
{
this->objCount = 0;
}
};
int Technics::objCount = 0;
class Computer : public Technics
{
private:
int cpu, ram, psu, hdd;
public:
Computer() {}
Computer(int price)
{
this->setPrice(price);
}
void setCpu(int cpu)
{
this->cpu = cpu;
}
int getCpu()
{
return this->cpu;
}
};
class Appliance : public Technics
{
private:
int height;
int width;
char* color;
char* type;
public:
Appliance(){}
Appliance(int height, int width)
{
this->height = height;
this->width = width;
}
void setWidth(int width)
{
this->width = width;
}
int getWidth()
{
return this->width;
}
};
void main()
{
//Creating array
Technics *_t[100];
// Adding some objects
_t[0] = new Computer();
_t[1] = new Computer();
_t[2] = new Appliance();
// I can access only properties of Technics, not Computer or Appliance
_t[0]->
int x;
cin >> x;
}

The line:
_t[0] = new Computer();
Creates a computer object and stores it as a Technics base pointer in the array (i.e. for all intents and purposes while in that array, it is a Technics object).
You need to cast back to the derived class to access members that are more derived than those in Technics:
static_cast<Computer*>(_t[0])->Your_Member();
Use dyncamic cast if you don't know which derived type it is - it will return the casted pointer on success and NULL on fail so it's kind of a type-check - it has big runtime overhead though, so try to avoid it :)
EDIT in response to your closing comment:
//Calculate the length of your dynamic array.
//Allocate the dynamic array as a pointer to a pointer to Technics - this is like
//Making an array of pointers each holding some Technics heirarchy object.
Technics** baselist = new Technics*[some_length];
//Populate them the same way as before:
baselist[0] = new Computer();
baselist[1] = new Appliance();
PS: you could also use std::vector which is dynamically changeable as opposed to just created at run time - it's the best option if your allowed to use it. It saves you making your own resizable array code. Google it ;)

That's because _t is a pointer to Technics not Computer or Appliance.
Give Technics an "object type" parameter e.g. an enum that is TechnicsType.Computer for Computer and TechnicsType.Applicance for Appliance, check that and cast to the appropriate type to get the class methods.

The solution is very very simple :)
The super-class must have the virtual functions of the subclasses declared in the class definition.
For example: if the super-class computer have a sub-class called laptop that have a function int getBatteryLife();, so the computer class must have the definition virtual int getBatteryLife() to be called in the vector of pointers of the type computer.

Because _t is a Technics pointer array and, there is not possible to access to derived classes attributes. Use a Visitor Pattern like this or downcast your pointer:
// visitor pattern
class Visitor
{
void accept(Appliance &ref) { // access Appliance attributes };
void accept(Computer & ref) { // access Computer attributes };
};
class Technics
{
....
virtual void visit(Visitor &) = 0;
};
class Appliance
{
....
virtual void visit(Visitor &v) { v.accept(*this); }
};
class Computer
{
....
virtual void visit(Visitor &v) { v.accept(*this); }
};

Yes, you can only access the properties of Technics, since your variable has type Technics. You have to cast it to your Computer or Appliance class in order to execute your additional methods.
You really have to think about your design here. Is it really appropiate? Why do you have all of the objects inside the same container? Especially if you have different methods to call..this doesn't make sense..
If you really want to call different methods, you probably have to use a switch statement to decide what type you have, then call the appropiate methods (I guess you want to iterate through the whole container, or else it doesn't make sense to have a big container with different objects).

Related

C++ polymorphism: how to create derived class objects

I have an abstract base class called BaseStrategy. It contains one pure virtual function calculateEfficiency(). There are two classes ConvolutionStrategy and MaxPoolStrategy which derive from this base class and implement their own specific version of calculateEfficiency().
Here is some code:
class BaseStrategy {
public:
explicit BaseStrategy();
virtual ~BaseStrategy() = default;
private:
virtual double calculateEfficiency(mlir::Operation* op) = 0;
};
class ConvolutionStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for convolution
return 1;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for MaxPool
return 1;
}
};
Now I have another class called StrategyAssigner. It has method calculateAllLayerEfficiencies() whose purpose is to iterate over all layers in a network. Depending on the type of layer there is a switch statement and should call the correct calculateEfficiency() depending on the layer type.
class StrategyAssigner final {
public:
explicit StrategyAssigner(){};
public:
void calculateAllLayerEfficiencies() {
// Logic to iterate over all layers in
// a network
switch (layerType) {
case Convolution:
// Call calculateEfficiency() for Convolution
break;
case MaxPool:
// Call calculateEfficiency() for MaxPool
break;
}
};
}
int main ()
{
StrategyAssigner assigner;
assigner.calculateAllLayerEfficiencies();
}
My question is, should I store references of objects Convolution and MaxPool in the class StrategyAssigner so that I can call the respective calculateEfficiency().
Or could you suggest a better way to call calculateEfficiency(). I don't really know how to create the objects (stupid as that sounds).
I can't make calculateEfficiency() static as I need them to be virtual so that each derived class can implemented its own formula.
If you included complete code I could give a more detailed answer, but you need to store BaseStrategy pointers that are initialized with derived class instances. Here's an example made from some of your code:
std::vector<std::unique_ptr<BaseStrategy>> strategies;
strategies.emplace_back(new ConvolutionStrategy);
strategies.emplace_back(new MaxPoolStrategy);
for (int i = 0; i < strategies.size(); ++i) {
std::unique_ptr<BaseStrategy>& pStrat = strategies[i];
pStrat->calculateEfficiency(...);
}
Note that this won't compile because I don't have enough details from the code you posted to make it so, but this shows how to exploit polymorphism in the way that you need.
Also, I used smart pointers for memory management; use these at your discretion.
You can indeed use runtime polymorphism here:
Declare ~BaseStrategy virtual (you are already doing it ;-)
If you are never going to instantiate a BaseStrategy, declare one of its methods as virtual pure, e.g. calculateEfficiency (you are already doing it as well!). I would make that method const, since it doesn't look it's going to modify the instance. And it will need to be public, because it will need to be accessed from StrategyAnalyser.
Declare calculateEfficiency as virtual and override in each of the subclasses. It could also be final if you don't want subclasses to override it.
I'd keep a std::vector of smart pointers to BaseStrategy at StrategyAssigner. You can use unique_ptrs if you think this class is not going to be sharing those pointers.
The key point now is that you create heap instances of the subclasses and assign them to a pointer of the base class.
class StrategyAssigner final {
public:
void addStrategy(std::unique_ptr<BaseStrategy> s) {
strategies_.push_back(std::move(s));
}
private:
std::vector<std::unique_ptr<BaseStrategy>> strategies_{};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
}
Then, when you call calculateEfficiency using any of those pointers to BaseStrategy, the runtime polymorphism will kick in and it will be the method for the subclass the one that will be actually called.
class ConvolutionStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "ConvolutionStrategy::calculateEfficiency()\n";
return 10;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "MaxPoolStrategy::calculateEfficiency()\n";
return 20;
}
};
class StrategyAssigner final {
public:
void calculateAllLayerEfficiencies() {
auto sum = std::accumulate(std::cbegin(strategies_), std::cend(strategies_), 0,
[](auto total, const auto& strategy_up) {
return total + strategy_up->calculateEfficiency(); });
std::cout << "Sum of all efficiencies: " << sum << "\n";
};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
assigner.addStrategy(std::make_unique<MaxPoolStrategy>());
assigner.calculateAllLayerEfficiencies();
}
// Outputs:
//
// ConvolutionStrategy::calculateEfficiency()
// MaxPoolStrategy::calculateEfficiency()
// Sum of all efficiencies: 30
[Demo]

Dynamic lists and polymorphism

I have a map of type < lookup_ID, vector< parentclass*>> each location in the map holds a vector of type child class. The idea behind this system is the ability to add a child into its associated map using an add(parentclass*) function and it would be able to find its associated vector of child type. I tried using templates and casting to get the vector to recognized the type of child input into the add function with no luck. I don't want to have to declare an add function for each child of parent, and no matter how I did it I had to declare a function for each type. I could take them out of the map but then again I'm left with the issue of calling each child for any function I want to implement. Is their no way to match types of polymorphic structures into dynamically allocated lists?`
class Piece
{
public:
pieceType ID;
//...
}
class Infantry :
public Piece
{
public:
//...
};
class Artillery :
public Piece
{
public:
//...
};
//...
//In some other classes somewhere
std::map<pieceType, std::vector<Piece*>*> units;
units.emplace(Infantry_, new std::vector<Infantry*>);
units.emplace(Artillery_, new std::vector<Artillery*>);
//...
template<typename T>
std::vector<T*> operator+(std::vector<T*> a, Piece * b) {
a.push_back(static_cast<T*>(b));
return a;
}
add(Piece * piece){
units.at(piece->ID) = units.at(piece->ID) + piece;
}
Also I am aware that this code has some errors, it was more for an example of what i'm trying to say.
You have to use virtual funciton to get the ID for each child class
class Piece
{
public:
virtual PieceType ID() const = 0;
}
class Artillery
{
public:
virtual PieceType ID() const override { /* return your ID for Artillery */ }
}
class Infantery
{
public:
virtual PieceType ID() const override { /* return your ID for Infantery */ }
}
There's no relation between std::vector<Piece*> and either of std::vector<Infantry*> or std::vector<Artillery*>, so your map can only contain std::vector<Piece*>s.
This is for good reason. Imagine you have a std::vector<Infantry*>, and put a pointer to it into your std::map<pieceType, std::vector<Piece*>*>. You could then insert an Artillery * into that through the map.
Rather than exposing the std::vector<Piece*> directly, you could expose a (read only) view of it that casts to the particular subtype.
Using the ranges library
auto asInfantry = ranges::view::transform([](Piece * p){ return static_cast<Infantry *>(p); });
auto asArtillery = ranges::view::transform([](Piece * p){ return static_cast<Artillery *>(p); });
class PieceMap
{
std::map<pieceType, std::vector<Piece*>> units;
public:
auto Infantry() { return units.at(Infantry_) | asInfantry; }
auto Artillery() { return units.at(Artillery_) | asArtillery; }
};

C++ command pattern

I'm trying to implement something like a command pattern to control serveral components with the same interface. Every component must implement the following interface.
class ComponentInterface {
public:
virtual int start() = 0;
virtual int stop() = 0;
};
Every derived component will implement some specific methods.
class Led : public ComponentInterface {
public:
/**
* Implements Interface methods
*/
int start() { return 0; }
int stop() { return 0; }
private:
int setIntensity(int attrs[], int returns[]) {
printf( "Set intensity called" );
return 1;
}
};
The main idea is that every subclass store the callable member functions in an array of pointers and in the ComponentInterface class will be implemented a methods that can call this functions based on the index of the command.
class ComponentInterface {
public:
...
// for storing the pointers
int (ComponentInterface::*commandsArray[10])(int[], int[]);
// to call the member functions
int command(int commandId, int attrsList[], int responseList[]) {
return (this->*commandsArray[commandId])(attrsList, responseList);
}
}
class Led : public ComponentInterface {
public:
Led(float* ledIntensity) {
// store the command in the array
this->commandsArray[0] = (&Led::setIntensity);
}
// redefine the array for pointers of this subclass
int (Led::*commandsArray[5])(int[], int[]);
};
I'm not familiar with C++ and I don't understand why it doesn't work, I have problems when calling the stored functions.
When testing with devC++, I get a segmentation fault. When i tried to test it in Visual Studio 2013 (Visual C++) and with the debugger it seems that in this row
(this->*commandsArray[commandId])(attrsList, responseList);
, the this object is pointing to the ComponentInterface object instead of the Led object.
Two things are immediately wrong in your code:
You can't "override a base class variable" and this line doesn't quite make sense in your derived class
// redefine the array for pointers of this subclass
int (Led::*commandsArray[5])(int[], int[]);
This cast is wrong
this->commandsArray[0] = (&Led::setIntensity);
it should rather be
this->commandsArray[0] = static_cast<int (ComponentInterface::*)(int*,int*)>(&Led::setIntensity);
Anyway a cleaner and safer way to achieve what you want is the following:
(Disclaimer: heavy stripping ahead, ignoring everything that doesn't immediately matter in the discussion)
class ComponentInterface {
..
std::vector<std::function<int (int[], int[])>> commandsArray;
}
Live Example
You could then store member functions with different signatures (bound to the right object) and just use the ComponentInterface container in your components.

Which is the better approach to check object type?

Approach 1:
class Employee
{
public:
virtual int calculateSalary() = 0;
};
class PermanentEmployee : public Employee {
const int salaryPerMonth;
public:
PermanentEmployee(int sal) : salaryPerMonth(sal){}
int calculateSalary() {
return salaryPerMonth;
}
};
class ContractEmployee : public Employee {
const int wagesPerHr;
int totalHour;
public:
ContractEmployee(int sal) : wagesPerHr(sal), totalHour(0){}
void setWorkingDuration(int time) {
totalHour = totalHour + time;
}
int calculateSalary() {
return wagesPerHr * totalHour;
}
};
class Manager {
list<Employee *> ls;
public:
void assignWorkingHour() {
list<Employee *>::iterator it;
for(it = ls.begin(); it != ls.end(); it++) {
Employee *emp = *it;
ContractEmployee* contractEmp = dynamic_cast<ContractEmployee* >(emp);
if(contractEmp) {
contractEmp->setWorkingDuration(5);
}
}
}
};
In problem, there are 2 type of Employee: PermanentEmployee and ContractEmployee.
There is a class called Manager which contains a list of all employee working under him.
For ContractEmployee, it has to invoke function setWorkingDuration(), which is being invoked in method assignWorkingHour of class Manager.
The problem is:
Here type of Employee is being determind by dynamic_cast operator and Manager has to know about all type of derive class of Employee.
Approach 2:
Add another member in class Employee:
enum TypeOfEmployee {CONTRACT, PERMANENT};
and check TypeOfEmployee to determine the type of Employee
Please tell me which is better or is there any alternative approach?
The better approach is to write code that doesn't require knowledge about the exact object type. Seems to me the most elegant way to deal with this is to move the setWorkingDuration() to the employee class. Probably like this:
class Employee
{
public:
// Calculates the salary for this employee.
// Returns the calculated salary.
virtual int calculateSalary() = 0;
// Sets the working duration. Does nothing if the employee is permanent.
// Returns true if Employee is on a contract, false if permanent.
virtual bool setWorkingDuration(int time)
{
return false;
}
};
class PermanentEmployee : public Employee
{
const int salaryPerMonth;
public:
PermanentEmployee(int sal) : salaryPerMonth(sal) {}
int calculateSalary()
{
return salaryPerMonth;
}
};
class ContractEmployee : public Employee
{
const int wagesPerHr;
int totalHour;
public:
ContractEmployee(int sal) : wagesPerHr(sal), totalHour(0) {}
int calculateSalary()
{
return wagesPerHr * totalHour;
}
bool setWorkingDuration(int time)
{
totalHour = totalHour + time;
return true;
}
};
class Manager
{
list<Employee *> ls;
public:
void assignWorkingHours()
{
list<Employee *>::iterator it;
for(it = ls.begin(); it != ls.end(); it++)
{
Employee* emp = *it;
emp->setWorkingDuration(5);
}
}
};
This way, the Manager class doesn't have to know whether the Employee is actually a PermanentEmployee or a ContractEmployee. That is what polymorphism gives you. Generally speaking if you have to use dynamic_cast<>, you may want to take another look at the design and see if you can omit it.
Well, the whole point of subtype polymorphism is to allow concrete subclasses to define their own behavior. What you're doing is matching against the type of object you have, and then specifying behavior dependent upon that. Essentially, you've duplicated the entire point of subtypes, and hence missed it. :)
My suggestion? Delegate this behavior to the object itself (not its manager) as a virtual method on Employee.
Of course you can you dynamic_cast operator as well as enum TypeOfEmployee but the last one has nothing common with polymorphism.
You should think why Manager sets working hours to PermanentEmployee. Is it Ok?
Another approach is to expand base class interface Employee with setWorkingDuration virtual method. Then in PermanentEmployee it will do nothing.
The others have already provided the answer (worth acceptance) for typical cases.
Here are some notes for less typical cases:
you can reduce your binary size (number of exported symbols), execution times, count of dynamic allocations, total memory usage, and chance for runtime errors if you can avoid using dynamic types at runtime.
removing virtuals and runtime polymorphism can reduce the size by more than 75%.
similarly, you can use variables to identify types or implementations in simple cases (e.g. your approach 2).
i made a simple test. it used multiple dynamic types (360, specifically), rtti, etc. a dylib of the size 588K was generated.
effectively replacing virtual methods and runtime polymorphism with function pointers brings it down to 130K. that's still 360 classes.
consolidating the implementation to a single class with variables only brought the dylib's size down to 10K.
again, this approach affects much more than binary size.
my point is that this is a good substitution under the right circumstances.
Approach three: keep track of contractors separately.
class Manager {
typedef list<Employee*> Employees; // Contains all employees, including contractors.
typedef list<ContractEmployee*> Contractors; // Contractors are in this list as well.
Employees employees;
Contractors contractors;
public:
void assignWorkingHour() {
for(Contractors::iterator it = contractors.begin(); it != contractors.end(); ++it) {
(*it)->setWorkingDuration(5);
}
}
int calculateEmployeeCost() {
int totalSalary = 0;
for (Employees::const_iterator it = employees.begin(); it != employees.end(); ++it) {
totalSalary += (*it)->calculateSalary();
}
return totalSalary;
}
};

A diamond-inheritance problem

Just for fun I am working on a XUL implementation for Windows. In XUL, UI elements can be written in XML like this:
<window width="800" height="600"></window>
I am considering a system for getting and setting element attributes. It's working pretty well but I am not certain if the use of diamond inheritance is potentially hazardous here. I've posted a complete code sample below:
#include <boost/lexical_cast.hpp>
#include <string>
#include <map>
class Attribute
{
public:
virtual void get(std::string & outValue) = 0;
virtual void set(const std::string & inValue) = 0;
static int String2Int(const std::string & inString)
{
return boost::lexical_cast<int>(inString);
}
static std::string Int2String(int inValue)
{
return boost::lexical_cast<std::string>(inValue);
}
};
class Width : public Attribute
{
public:
Width(){}
virtual void get(std::string & outValue)
{
outValue = Int2String(getWidth());
}
virtual void set(const std::string & inValue)
{
setWidth(String2Int(inValue));
}
virtual int getWidth() const = 0;
virtual void setWidth(int inWidth) = 0;
};
class Height : public Attribute
{
public:
Height(){}
virtual void get(std::string & outValue)
{
outValue = Int2String(getHeight());
}
virtual void set(const std::string & inValue)
{
setHeight(String2Int(inValue));
}
virtual int getHeight() const = 0;
virtual void setHeight(int inHeight) = 0;
};
class Element : public Width, // concerning the is-a vs has-a philosophy
public Height // => see my note below
{
public:
Element() :
mWidth(0),
mHeight(0)
{
// STATIC CAST NEEDED HERE OTHERWISE WE GET COMPILER ERROR:
// error C2594: '=' : ambiguous conversions from 'Element *const ' to 'Attribute *'
mAttrControllers["width"] = static_cast<Width*>(this);
mAttrControllers["height"] = static_cast<Height*>(this);
}
void setAttribute(const std::string & inAttrName, const std::string & inAttrValue)
{
Attributes::iterator it = mAttrControllers.find(inAttrName);
if (it != mAttrControllers.end())
{
Attribute * attribute = it->second;
attribute->set(inAttrValue);
}
}
std::string getAttribute(const std::string & inAttrName)
{
std::string result;
Attributes::iterator it = mAttrControllers.find(inAttrName);
if (it != mAttrControllers.end())
{
Attribute * attribute = it->second;
attribute->get(result);
}
return result;
}
virtual int getWidth() const
{
return mWidth;
}
virtual void setWidth(int inWidth)
{
mWidth = inWidth;
}
virtual int getHeight() const
{
return mHeight;
}
virtual void setHeight(int inHeight)
{
mHeight = inHeight;
}
private:
typedef std::map<std::string, Attribute *> Attributes;
Attributes mAttrControllers;
int mWidth;
int mHeight;
};
int main()
{
Element el;
el.setAttribute("width", "800");
el.setAttribute("height", "600");
int w = el.getWidth();
int h = el.getHeight();
return 0;
}
I think it's ok since the base class Attributes has no data members, so no conflicts can arise there. But I thought I'd check with the community. Your insights are much appreciated!
Edit
About the "is-a" vs "has-a", and "favor composition over inheritance" remarks I have this to say:
There
is an advantage to inheritance here.
If Element inherits Width then it is
forced to implement the getWidth and
setWidth methods. So adding an
attribute implies an 'automatic'
update of Element's interface.
I originally named these classes
AttributeController, WidthController
and HeightController, but I found
them too verbose. You could say that my Element is an Attribute controller. (Ok, that's lame, but not untrue!)
Further proof: the definitions of Width and Height
do not contain any data members. The
Element class actually has them.
The Width and Height classes only
provide the interfaces. So it's more of a can-do relationship.
In your scenario, Element should probably not inherit from Width and Height, but instead, Width and Height should be data members of element. It's composition as opposed to is-a since arguably an Element is-not-a Width or Height but is composed of a Width and Height (and probably some other stuff too).
Element should inherit Width only if you need to use Element objects as Width ones . Inheritance is not for code reuse.
Maybe would be worth for you taking a look into boost::program_options library. I like the fancy way they have for registering properties.
If I was going to do this, I'd do a virtual inherit on Attribute. I don't think it will matter significantly, but that will minimize the duplication if it does end up mattering.
First of all, use virtual inheritance if you are facing face a diamond problem, that is, use public virtual instead of just public on the base classes.
Secondly, it's not well defined what your get- and set-will do as there are two implementations. The only time I use multiple inheritance is when I extend pure virtual classes (aka interfaces). It's a good reason for Java to not support multiple inheritance.
Third, and more importantly, this seems like a classic case between a misunderstanding of inheritance ("is a") vs aggregation ("has a") in object orientation. You can two very simple guidelines when determining if a class should inherit another class. If you have class A and class B which inherits class A, the sentence "A is a B" should make sense. If "A has a B" sounds better, you should really consider letting B be a member of A instead.
In your case the sentences "Element is a Height" and "Element is a Width" really doesn't make sense. "Element has a Height" makes perfectly sense.