I'm trying to find a way to get an iterator to work on a list of custom objects and a list of objects derived from that custom object. My, perhaps misguided, goal is to allow me to leave the "production" code and objects intact yet accessible from the "experimental/extended" things that I'm trying out.
Here's a pretty minimal example of what I'm trying to do.
#include <iostream>
#include <list>
using std::cout;
using std::endl;
using std::cin;
using std::list;
struct comp{
double x,y;
void print(){
cout << "x: " << x << endl;
cout << "y: " << y << endl;
}
comp(){
x = 0;
y = 0;
}
comp(double X, double Y){
x = X;
y = Y;
}
// Standard/Tested Member Functions
};
struct base{
list<comp> components;
double known, tested, variables;
void print_comps(){
for (list<comp>::iterator it = components.begin(); it != components.end(); ++it){
// Ideally, this function should work for comp1 and comp1x
// as inherited in the basex class
it->print();
}
}
// Standard/Tested Member Functions
};
struct compx : comp{
double w,z;
double some, alter, nates;
void print(){
cout << "x: " << x << endl;
cout << "y: " << y << endl;
cout << "w: " << w << endl;
cout << "z: " << z << endl;
}
compx(){
x = 0;
y = 0;
z = 0;
w = 0;
}
compx(double X, double Y, double Z, double W){
x = X;
y = Y;
z = Z;
w = W;
}
// Experimental/Un-tested Member Functions
};
struct basex : base{
list<compx> components;
double exper, imen, tal;
// void print_comps(){} // This should be inherited from base
// Experimental/Un-tested Member Functions
};
int main(){
base compilation1;
compilation1.components.push_back(comp(1,2));
compilation1.components.push_back(comp(3,4));
cout << "printing normal struct" << endl;
compilation1.print_comps();
cout << endl;
basex compilation2;
compilation2.components.push_back(compx(9, 5, 5, 6));
compilation2.components.push_back(compx(7, 2, 1, 8));
cout << "printing extended struct" << endl;
compilation2.print_comps(); // Prints nothing
cout << endl;
cout << "Printing via specific iterator" << endl;
for (list<compx>::iterator it = compilation2.components.begin(); it != compilation2.components.end(); ++it){
it->print(); // Works as expected.
}
cout << endl << endl << "Press ENTER to exit." << endl; cin.get();
return 0;
}
Ideally, I would be able to iterate over both the original class and the extended class in the same functions so I don't clutter the extended class with all the original code. This would allow me to simply move code from the extended class to the original class as those variables or functions are proven or matured.
Background:
I'm not married to lists -- any other iterable class would be fine.
I'm not a developer -- I'm a ChemE trying to make daily tasks a bit easier without breaking what I've already built.
Branches in a git repository are not a great solution because other non-developer, potentially code-challenged, folks may try to extend this. Getting them to use even one branch would be a miracle.
I'm using g++ 7.4.0 on Linux (Lubuntu) and 6.3.0 on Windows 7.
TL;DR:
Is there a way to get an iterator of list<parent_object> to also iterate over list<child_object>?
This could be solved by having base as a template http://cpp.sh/7r2x6a
template<typename T>
struct base
{
list<T> components;
double known, tested, variables;
void print_comps(){
for (auto it = components.begin(); it != components.end(); ++it){
// Ideally, this function should work for comp1 and comp1x
// as inherited in the basex class
it->print();
}
}
// Standard/Tested Member Functions
};
If you're okay with not being able to mix comp and compx objects together in the same list, then you can use a templated function to avoid duplicate code.
For example, you can do the following in your struct base:
struct base{
list<comp> components;
double known, tested, variables;
void print_comps() {print_comps_aux<comp>(components);}
protected:
template <typename CompType> void print_comps_aux(list<CompType> & compsArg)
{
for (typename list<CompType>::iterator it = compsArg.begin(); it != compsArg.end(); ++it){
it->print();
}
}
// Standard/Tested Member Functions
};
... and then in your struct basex you can just have this:
[...]
void print_comps() {print_comps_aux<compx>(components);}
Related
This question already has answers here:
Storing derived object into container of base type
(2 answers)
What is object slicing?
(18 answers)
Closed 3 years ago.
An acquaintance of mine has shared some sample code that exhibits somewhat strange behavior. Basically the sample code has a base class and a derived class, which overrides a virtual method. There are two sets of STL lists, each containing two lists (i.e. four STL lists in all).
Set-A
List of instances of base class, containing derived instances
List of instances of derived class, containing derived instances
Set-B
List of pointers to base class, containing pointers to derived instances
List of pointers to derived class, containing pointers to derived instances
In Set-A the overridden method is not executed in the case where we have a list of instances of base class, containing derived instances.
The sample code follows:
#include <iostream>
#include <list>
using namespace std;
//***********************************************************************
//
//***********************************************************************
class Base {
protected:
int i;
public:
//-----------------------------------------------------------------------
//
//-----------------------------------------------------------------------
Base(int m)
{
i = m;
}
//-----------------------------------------------------------------------
//
//-----------------------------------------------------------------------
int get_i()
{
return i;
}
//-----------------------------------------------------------------------
//
//-----------------------------------------------------------------------
virtual int xyz()
{
return i;
}
// Returns the value of the base
// class attribute
};
//***********************************************************************
//
//***********************************************************************
class Derived : public Base {
protected:
int j;
public:
//-----------------------------------------------------------------------
//
//-----------------------------------------------------------------------
Derived(int m, int n) : Base(m)
{
j = n;
}
//-----------------------------------------------------------------------
//
//-----------------------------------------------------------------------
int get_j()
{
return j;
}
//-----------------------------------------------------------------------
//
//-----------------------------------------------------------------------
int xyz()
{
return j;
}
// Returns the value of the derived
// class attribute
};
//***********************************************************************
//
//***********************************************************************
typedef list<Base> BaseList;
typedef list<Base>::iterator BaseIterator;
typedef list<Derived> DerivedList;
typedef list<Derived>::iterator DerivedIterator;
typedef list<Base*> BasePtrList;
typedef list<Base*>::iterator BasePtrIterator;
typedef list<Derived*> DerivedPtrList;
typedef list<Derived*>::iterator DerivedPtrIterator;
//-----------------------------------------------------------------------
//
//-----------------------------------------------------------------------
main()
{
Derived* d[5];
for (int k1 = 0; k1 < 5; k1++)
{
d[k1] = new Derived(k1, 2 * k1);
// The base attribute ('i') has value 0 through 4
// The derived attribute value ('j') is double that
}
// Instance collection declarations
BaseList bcollection;
BaseIterator biter, beol;
DerivedList dcollection;
DerivedIterator diter, deol;
// Pointer collection declarations
BasePtrList bpcollection;
BasePtrIterator bpiter, bpeol;
DerivedPtrList dpcollection;
DerivedPtrIterator dpiter, dpeol;
for (int k2 = 0; k2 < 5; k2++)
{
//Insert elements in base collection
bcollection.insert(bcollection.begin(), *d[k2]);
//Insert the SAME elements in the derived collection
dcollection.insert(dcollection.begin(), *d[k2]);
//Insert elements in base-ptr collection
bpcollection.insert(bpcollection.begin(), d[k2]);
//Insert the SAME elements in the derived-ptr collection
dpcollection.insert(dpcollection.begin(), d[k2]);
}
cout << "** Instance-collection behavior **\n";
// Iterate through the base collection and execute the
// virtual method "xyz()" on each element
cout << "Base collection:" << endl;
beol = bcollection.end();
for (biter = bcollection.begin(); biter != beol; biter++)
cout << " get_i()=" << (*biter).get_i() << ", xyz()="
<< (*biter).xyz() << endl;
// Iterate through the derived collection and execute the
// virtual method "xyz()" on each element. Since we entered
// the exact same elements in both lists, the EXPECTED output
// is the same as before.
//
// Check out for yourself ;-(
//
cout << "Derived collection:" << endl;
deol = dcollection.end();
for (diter = dcollection.begin(); diter != deol; diter++)
cout << " get_i()=" << (*diter).get_i() << ", xyz()="
<< (*diter).xyz() << endl;
cout << "The exact same elements were entered in both collections.\n"
<< "Is the output the same in both the cases?\n";
cout << "\n\n** Pointer-collection behavior **\n";
// Iterate through the base-pointer collection and execute the
// virtual method "xyz()" on each element
cout << "Base-pointer collection:" << endl;
bpeol = bpcollection.end();
for (bpiter = bpcollection.begin(); bpiter != bpeol; bpiter++)
cout << " get_i()=" << (*bpiter)->get_i() << ", xyz()="
<< (*bpiter)->xyz() << endl;
// Iterate through the derived-pointer collection and execute the
// virtual method "xyz()" on each element. Since we entered
// the exact same elements in both lists, the EXPECTED output
// is the same as before.
//
// No surprises this time around :-(
cout << "Derived-pointer collection:" << endl;
dpeol = dpcollection.end();
for (dpiter = dpcollection.begin(); dpiter != dpeol; dpiter++)
cout << " get_i()=" << (*dpiter)->get_i() << ", xyz()="
<< (*dpiter)->xyz() << endl;
cout << "The exact same elements were entered in both collections.\n"
<< "Is the output the same in both the cases?\n";
}
I have the following problem: I wanted to redo a project from good old C to C++ and make everything class(y) :) and keep it scalable from the beginning.
It is a simulation of cells (being part of a swarm) on a grid, so I decided the following structure:
class Simulation has an instance of
class Grid has an instance of
class Swarm has an instance of
class Cell
I defined the classes in separate header files. Then I need, of course, to be able to call functions in grid, swarm and cell as well. I wanted to do it straight forward:
Simulation mysim;
mysim.get_grid(0).any_function_here();
with the grid as return parameter
Grid Sim::get_grid(int grid_no)
{
std::cout << "sim.get_grid(" << grid_no << ") called." << std::endl;
if (grid_no <= amount_of_grids)
return this->test;//##//this->gridlist[grid_no];
else
std::cout << "you have not created this grid number yet" << std::endl;
Grid dummy;
return dummy;
}
It calls the function and works as long as no changes in the grid are made. These seem to be lost in space. Probably a pointer error, but I cannot find an error, since exactly the same code is working for the Simulation class...
More source:
int Grid::create_swarm(std::string name)
{
Swarm new_swarm;
new_swarm.set_name("Protoswarm");
swarmlist.push_back(new_swarm);
this->amount_of_swarms ++;
std::cout << "amount_of_swarms = " << amount_of_swarms << std::endl;
return 0;
}
Swarm Grid::get_swarm(int swarm_no)
{
std::cout << "grid.get_swarm(" << swarm_no << ") called." << std::endl;
if (swarm_no <= amount_of_swarms)
return swarmlist[swarm_no];
else
std::cout << "oh oh - you have not this swarm in here..." << std::endl;
Swarm dummy;
return dummy;
}
I can call the create_swarm function as often as I want, but the swarms do never appear and the counter does not raise in that grid, just temporarily as long as the funtion is in there. Am I missing something? Is it really just a pointer error? Why does this code work if I call it like this:
Grid newgrid;
newgrid.create_swarm();
A quickly c&p'ed MWE
#include <iostream>
#include <string>
#include <vector>
class Sim
{
public:
Sim();
virtual ~Sim();
Grid get_grid(int grid_no);
protected:
private:
std::vector<Grid> gridlist;
int amount_of_grids = -1;
};
class Grid
{
public:
Grid();
virtual ~Grid();
int set_size(int x, int y);
int create_swarm(std::string name);
Swarm get_swarm(int swarm_no);
void print_swarms();
protected:
private:
std::vector<Swarm> swarmlist;
int amount_of_swarms = -1;
/*static const*/ int size_x;
/*static const*/ int size_y;
std::vector<std::vector<Field>> fields;
std::string gridname;
};
Grid Sim::get_grid(int grid_no)
{
std::cout << "sim.get_grid(" << grid_no << ") called." << std::endl;
if (grid_no <= amount_of_grids)
return this->gridlist[grid_no];
else
std::cout << "you have not created this grid number yet" << std::endl;
Grid dummy;
return dummy;
}
int Grid::create_swarm(std::string name)
{
Swarm new_swarm;
new_swarm.set_name("Protoswarm");
swarmlist.push_back(new_swarm);
this->amount_of_swarms ++;
std::cout << "amount_of_swarms = " << amount_of_swarms << std::endl;
return 0;
}
Swarm Grid::get_swarm(int swarm_no)
{
std::cout << "grid.get_swarm(" << swarm_no << ") called." << std::endl;
if (swarm_no <= amount_of_swarms)
return swarmlist[swarm_no];
else
std::cout << "oh oh - you have not this swarm in here..." << std::endl;
Swarm dummy;
return dummy;
}
using namespace std;
int main(int argc, char* argv[])
{
Sim mysim;
mysim.create_grid();
mysim.get_grid(0).create_swarm("Alpha-Swarm");
mysim.get_grid(0).create_swarm("Betaa-Swarm"); //doesn't work
Grid newgrid;
newgrid.create_swarm("Gamma-Swarm");
newgrid.create_swarm("Delta-Swarm"); // works, but is not needed.
return 0;
}
Grid Sim::get_grid(int grid_no) {...}
You are returning by value, not by reference. That means that what you are returning is a copy of your actual member. In your case, however, you want to be returning by reference in order to be able to make changes to the original object. Your code would become
Grid& Sim::get_grid(int grid_no) {...}
Keep in mind, however, that you will not be able to return any temporaries that way (such as your dummy Grid), so you will need to change your methods to circumvent this issue. If you do not want to do this, you could still return a pointer, although this would change the syntax a little.
Your get_grid and get_swarm methods return copies of original array items. You should return reference (or a pointer) to Grid or Swarm instead.
I'm trying to use boost to create a multidimensional array and I want said array to be a member of some class.
However I find two problems with it:
1 - I need to declare the size of the array with
boost::extents[2][2]
Everytime I want to use the array. Otherwise I get the following error:
a.out: /usr/include/boost/multi_array/base.hpp:136: Referenceboost::detail::multi_array::value_accessor_n<T, NumDims>::access(boost::type<Reference>, boost::detail::multi_array::value_accessor_n<T, NumDims>::index, TPtr, const size_type*, const index*, const index*) const [with Reference = boost::detail::multi_array::sub_array<double, 1ul>; TPtr = double*; T = double; long unsigned int NumDims = 2ul; boost::detail::multi_array::value_accessor_n<T, NumDims>::index = long int; boost::detail::multi_array::multi_array_base::size_type = long unsigned int]: Assertion `size_type(idx - index_bases[0]) < extents[0]' failed.
2 - Ok, maybe this is just part of how multidimensional arrays work in C++ with Boost, I'm going to write my code accepting every function "declares" the array. However, if I do this I find the array is empty.
Here's a snippet of code that reproduces this problem. During the "construction" of the class the array should be filled. However, the line
cout << "Result: " << testing.getArrayMember(0,1) << endl;
outputs "Result: 0".
#include <iostream>
#include "boost/multi_array.hpp"
typedef boost::multi_array<double, 2> dbl_array;
using namespace std;
class TestClass {
public:
dbl_array darray;
TestClass(double x);
void fillArray(double x);
double getArrayMember(int i, int j);
};
TestClass::TestClass(double x) {
dbl_array darray(boost::extents[2][2]);
cout << "Class constructor called" << endl;
fillArray(x);
}
void TestClass::fillArray(double x) {
cout << "Filling array" << endl;
dbl_array darray(boost::extents[2][2]); // Without this line, the code fails at runtime
darray[0][0] = x;
darray[1][0] = 2.0*x;
darray[0][1] = 3.0*x;
darray[1][1] = 4.0*x;
cout << "Array filled" << endl;
}
double TestClass::getArrayMember(int i, int j) {
dbl_array darray(boost::extents[2][2]); // Without this line, the code fails at runtime
return darray[i][j];
}
int main() {
TestClass testing = TestClass(5.0);
// The result is 0 in the end
cout << "Result: " << testing.getArrayMember(0,1) << endl;
return 0;
}
What am I doing wrong here?
Option 1 is to use an initialisation list:
TestClass::TestClass(double x) : darray(boost::extents[2][2]) {
cout << "Class constructor called" << endl;
fillArray(x);
}
Since otherwise the member of the class darray is created using the default constructor and not through your line
dbl_array darray(boost::extents[2][2]);
as you believe.
This is the same answers as given in initialize boost::multi_array in a class
However, I want to add the following bit, which I think it is relevant in this situation:
It might be necessary for you to generate the array after performing some kind of operation in the constructor of your class. You can achieve this using "resize" after the array has been created by the default constructor.
Ie, instead of
TestClass::TestClass(double x) {
dbl_array darray(boost::extents[2][2]);
cout << "Class constructor called" << endl;
fillArray(x);
}
you could have
TestClass::TestClass(double x) {
darray.resize(boost::extents[2][2]);
cout << "Class constructor called" << endl;
fillArray(x);
}
I am still wrapping my head around classes and am still new to C++. My assignment is:
Create three small classes unrelated by inheritance - classes
Building, Car and Bicycle. Give each class some unique appropriate
attributes and behaviors that it does not have in common with other
classes.
Write an abstract class CarbonFootprint with only a pure virtual
getCarbonFootprint method.
Have each of your classes inherit from that abstract class and
implement the getCarbonFootprint method to calculate an appropriate
carbon footprint for that class (check out a few websites that explain
how to calculate carbon footprints).
Write an application that creates objects of each of the three
classes, places pointers to those objects in a vector of
CarbonFootprint pointers, then iterates through the vector,
polymorphically invoking each object's getCarbonFootprint method.
For each object, print some identifying information and the object's
carbon footprint.
I am having trouble trying to figure out how to iterate through my vector <CarbonFootPrint>. I also do not know if the objects being created are actually being put into this vector. My code so far is:
#include <iostream>
#include <vector>
using namespace std;
class CarbonFootPrint
{
//class declarations
public:
virtual double getCarbonFootPrint();
};
//class implementation
double CarbonFootPrint::getCarbonFootPrint()
{
return 0;
}
class Building : CarbonFootPrint
{
//class declarations
public:
Building(double e = 0, int m = 12); //constructor
~Building(); //destructor
double setElectric();
virtual double getCarbonFootPrint();
private:
double electric;
int months;
};
//class implementation
Building::Building(double e, int m)
{
electric = e;
months = m;
}
Building::~Building()
{
}
double Building::setElectric()
{
cout << "Enter your monthly electric in KWH: " << endl;
cin >> electric;
return electric;
}
double Building::getCarbonFootPrint()
{
//I would like to print out the variable information for each object created
//and then
cout << "The carbon footprint for this house is " << endl;
//when it iterates through the vector.
return(electric * months);
}
class Car : CarbonFootPrint
{
public:
Car(double = 0, double = 0); //constructor
~Car(); //destructor
double setYearlyMiles();
double setAverageMPG();
virtual double getCarbonFootPrint();
private:
double yearlyMiles, averageMPG;
int co2 = 9;
};
//class implementation
Car::Car(double ym, double mpg)
{
yearlyMiles = ym;
averageMPG = mpg;
}
Car::~Car()
{
}
double Car::setYearlyMiles()
{
cout << "Enter in your yearly miles: " << endl;
cin >> yearlyMiles;
return yearlyMiles;
}
double Car::setAverageMPG()
{
cout << "Enter in your average miles per gallon: " << endl;
cin >> averageMPG;
return averageMPG;
}
double Car::getCarbonFootPrint()
{
//I would like to print out the variable information for each object created
//and then
cout << "The carbon footprint for this car is " << endl;
//when it iterates through the vector.
return((yearlyMiles * averageMPG) * co2);
}
class Bicycle : CarbonFootPrint
{
public:
Bicycle(double = 0, int = 34); //constructor
~Bicycle(); //destructor
double setMiles();
virtual double getCarbonFootPrint();
private:
int calories;
double miles;
};
//class implementation
Bicycle::Bicycle(double m, int c)
{
miles = m;
calories = c;
}
Bicycle::~Bicycle()
{
}
double Bicycle::setMiles()
{
cout << "Enter in number of miles: " << endl;
cin >> miles;
return miles;
}
double Bicycle::getCarbonFootPrint()
{
//I would like to print out the variable information for each object created
//and then
cout << "The carbon footprint for this bicycle is " << endl;
//when it iterates through the vector.
return (miles * calories);
}
Here is my main program:
int main()
{
vector <CarbonFootPrint> *list;
int answer, i;
cout << "Welcome to the Carbon Footprint Calculator!\n" << endl;
do
{
cout << "Main Menu\n" << endl;
cout << "1: Set house info.\n" << endl;
cout << "2: Set car info.\n" << endl;
cout << "3: Set bicycle info.\n" << endl;
cout << "4: Get carbon footprint for all items set.\n" << endl;
cin >> answer;
switch (answer)
{
case 1:
{
cout << "\n" << endl;
Building *anotherBuilding;
anotherBuilding = new Building;
anotherBuilding->setElectric();
cout << "\n" << endl;
break;
}
case 2:
{
cout << "\n" << endl;
Car *anotherCar;
anotherCar = new Car;
anotherCar->setYearlyMiles();
anotherCar->setAverageMPG();
cout << "\n" << endl;
break;
}
case 3:
{
cout << "\n" << endl;
Bicycle *anotherbike;
anotherbike = new Bicycle;
anotherbike->setMiles();
cout << "\n" << endl;
break;
}
case 4:
{
//have it iterate through the vector and print out each carbon footprint.
break;
}
default:
{
cout << answer << " is not a valid option" << endl;
break;
}
}
}
while (answer != 4);
system("pause");
return 0;
}
Any help or guidance is greatly appreciated! Thank you for your time!
Re: your comments on R Sahu's post (I'm too new to be allowed to comment on other posts)
You cannot access the base class because it has defaulted to private,
class Building : CarbonFootPrint
class Car : CarbonFootPrint
class Bicycle : CarbonFootPrint
are all inheriting from CarbonFootPrint privately, which represents a "has-a" relationship, in this case although semantically a car has-a carbon foot print you're actually trying to make an "is-a" relationship, as these are all objects that implement the base class, possibly a better name for CarbonFootPrint could be CarbonFootPrintProducer.
The fix here is simply make them all publically inherited
class Name : public Base
You missed a crucial thing from:
Write an application that creates objects of each of the three classes, places pointers to those objects in a vector of CarbonFootprint pointers, then iterates through the vector, polymorphically invoking each object's getCarbonFootprint method.
Instead of
vector <CarbonFootPrint> *list; // Pointer to a vector of CarbonFootPrint objects.
You need to use
vector <CarbonFootPrint*> list; // A vector of CarbonFootPrint pointers.
Instead of
{
cout << "\n" << endl;
Building *anotherBuilding;
anotherBuilding = new Building;
anotherBuilding->setElectric();
cout << "\n" << endl;
break;
}
Use
{
cout << "\n" << endl;
Building *anotherBuilding;
anotherBuilding = new Building;
anotherBuilding->setElectric();
// Add the pointer to the list of pointers.
list.push_back(anotherBuilding);
cout << "\n" << endl;
break;
}
Make similar changes to the other object types.
At the end, call CarbonFootPrint() on the objects:
for (auto item : list )
{
item->CarbonFootPrint();
}
and delete the objects:
for (auto item : list )
{
delete item;
}
R Sahu covered almost all of it, the only bit I see remaining is;
Write an abstract class CarbonFootprint with only a pure virtual getCarbonFootprint method.
to which your class is not abstract as the function is not pure virtual, to do this simply add = 0
virtual double getCarbonFootPrint() = 0;
Pure virtual functions are ones that don't count as implemented, any class containing a pure virtual function is called "abstract" and cannot be instantiated. In this case it would have helped you identify your vector of CarbonFootPrint rather than CarbonFootPrint* to them, as the instantiations would be picked up by the compiler, although knowing template compiler errors you'd have had a couple hundred lines of error message for this simple mistake.
For full disclosure: a pure virtual function can actually be defined, e.g.;
virtual double getCarbonFootPrint() = 0;
double CarbonFootPrint::getCarbonFootPrint()
{
// some code
return 0;
}
which can then be called from any derived class
double Building::getCarbonFootPrint()
{
return CarbonFootPrint::getCarbonFootPrint();
}
This is legal C++, allows you to define a default implementation, and still CarbonFootprint is an abstract class.
So I have this problem where the output prints the address of my pointer, I have no idea why this happens cuz the pointers is not modified at all
Heres the code:
using namespace std;
class AndroideAbstracto {
protected:
int *vida;
int *fuerza;
int *velocidad;
public:
void setvalores(int vi, int fu, int ve) {
velocidad = &ve;
vida = &vi;
fuerza = &fu;
};
virtual void imprimir(void) = 0;
};
class Androide : public AndroideAbstracto {
public:
void imprimir() {
std::cout << "Caracteristicas del androide:" << endl;
cout << "Velocidad = " << *velocidad << endl;
cout << "Vida = " << *vida << endl;
cout << "Fuerza = " << *fuerza << endl;
};
};
class Decorator : public AndroideAbstracto {
protected:
AndroideAbstracto *AndroideDec;
public:
Decorator(AndroideAbstracto* android_abs) {
AndroideDec = android_abs;
}
virtual void imprimir(void) = 0;
};
class Androide_Con_Habi : public Decorator {
protected:
string habilidad;
public:
Androide_Con_Habi(AndroideAbstracto* android_abs, string habi) : Decorator(android_abs) {
habilidad = habi;
}
virtual void imprimir() {
AndroideDec->imprimir();
cout << "La habilidad especial del androide es: " << habilidad << endl;
}
};
class Androide_Elegido : public Decorator {
protected:
bool elegido;
public:
Androide_Elegido(AndroideAbstracto *android_abs, bool es) : Decorator(android_abs) {
elegido = es;
}
virtual void imprimir() {
if (elegido) {
// *vida =(*vida) * 2; //Im quite new to C++ so im not really
// *fuerza *=2; //sure how should I multiply these pointers
// *velocidad *=2;
// AndroideDec->setvalores(vida*2,fuerza*2,velocidad*2);
AndroideDec->imprimir();
cout << "Este androide es uno de los elegidos";
}
}
};
int main(int argc, char *argv[]) {
Androide *andro = new Androide();
andro->setvalores(600, 700, 300);
andro->imprimir();
Androide_Con_Habi *andro_con_habi = new Androide_Con_Habi(andro, "Volar");
andro_con_habi->imprimir();
Androide_Elegido *superpoderoso = new Androide_Elegido(andro, true);
superpoderoso->imprimir();
delete superpoderoso;
delete andro;
delete andro_con_habi;
return 0;
}
I have no idea why but this prints:
Caracteristicas del androide:
Velocidad = 300
Vida = 600
Fuerza = 700
Caracteristicas del androide:
Velocidad = 300
Vida = 152436744
Fuerza = -1074718788
La habilidad especial del androide es: Volar
Caracteristicas del androide:
Velocidad = 300
Vida = 152436744
Fuerza = 1
Este androide es uno de los elegidos
void setvalores(int vi, int fu, int ve) {
velocidad = &ve;
vida = &vi;
fuerza = &fu;
};
The pointers to vi, fu, and ve get invalidated when the function returns. You're not seeing addresses being printed, but simply garbage.
Your entire design doesn't and shouldn't need to use pointers though.
What you're seeing is the addresses of the formal parameters of your function. Essentially meaningless values that aren't useful, and will essentially be pointers to a random position on your stack - wherever the stack happened to be when you called the constructor. You would basically never be interested in these values unless you were trying to learn more about how your computer and compiler worked.
It's very important to understand what pointers do and when they're appropriate, and what their implications are.
In this case, it's not suitable to use pointers because:
You're trying to store data inside your class, and the type you're storing is:
The same size as a pointer anyway (int)
There's no reason to keep the memory for it outside your class (none shown, anyway)
even if you needed to, references would be less error-prone (int & instead of int *)
Also, you're using the heap to make an instance of your class, when the stack will do just fine.
I suspect this is what you intended:
class AndroideAbstracto {
protected:
int vida;
int fuerza;
int velocidad;
public:
void setvalores(int vi, int fu, int ve) {
velocidad = ve;
vida = vi;
fuerza = fu;
};
virtual void imprimir(void) = 0;
};
class Androide : public AndroideAbstracto {
public:
void imprimir() {
std::cout << "Caracteristicas del androide:" << endl;
cout << "Velocidad = " << velocidad << endl;
cout << "Vida = " << vida << endl;
cout << "Fuerza = " << fuerza << endl;
};
};
Note the lack of *'s both in the types of the class members, and when printing out the values.
One not terribly good, but syntactically correct use of pointers here would be to query multiple values in the class with a single call (put in either class):
void getvalores(int *vi, int *fu, int *ve) {
if (vi)
*vi = vida;
if (fu)
*fu = fuerza;
if (ve)
*ve = velocidad;
}
called like this, for example:
int vida, velocidad;
andro->getvalores(&vida, NULL, &velocidad);
cout << "Velocidad = " << velocidad << endl;
cout << "Vida = " << vida << endl;
Here we've passed the address of the stack variables vida and velocidad as pointers, and passed NULL where we could have passed an additional address because we don't want the value of fuerza. We then assign to the memory pointed to by the passed in pointers if they're not null, and when the function returns, the stack variables have the values from the class.
You shouldn't actually do this, of course - you should just provide access to the values another way, either directly by making them public, or by adding functions that just return them.
public:
int Vida() {
return vida;
}
Then you can just do:
cout << "Vida = " << andro->Vida() << endl;
And, of course, unless there is a reason to use the heap to create your Androide instance, you should just use stack memory instead of the heap.
Androide andro;
instead of
Androide *andro = new Androide();