I have a mother class and a derived daughter class. I am trying to access the protected variable 'familystuff' in the derived class. Both ways that I am trying to access it aren't working. When I compile and run it, I get the following output:
5 3 1
1
Familie 32768
FOO 32767
class Mother
{
private:
int motherstuff;
protected:
int familystuff;
public:
int everyonesstuff;
void SetStuff(int a, int b, int c){
motherstuff = a;
familystuff = b;
everyonesstuff = c;
}
void Show(){
cout << motherstuff << " " << familystuff << " " <<everyonesstuff << endl;
}
};
class Daughter : public Mother
{
public:
Daughter()
{
a = familystuff + 1;
}
void Show(){
cout << "Familie " << a << endl;
}
int foo() { return familystuff;}
private:
int a;
};
int main(){
Mother myMum;
myMum.SetStuff(5,3,1);
myMum.Show();
cout << myMum.everyonesstuff << endl;
Daughter myDaughter;
myDaughter.Show();
cout << "FOO " << myDaughter.foo() << endl;
}
You don't have a clear concept in object oriented programming. When you create two objects, then they are completely different from each other. They do not interact with each other until they are forced.So,
myMum and myDaughter are seperate objects and they do not share the values of their variables.
The last two outputs are basically garbage values. You have not initialized myDaughter's familystuff
So, if you want to access protected members from derived class, you need to write the following :
int main()
{
Daughter myDaughter(5,3,1);
myDaughter.Show();
cout << "FOO " << myDaughter.foo() << endl;
}
Change the Daughter's constructor to the following :
Daughter(int x,int y,int z)
{
SetStuff(x,y,z);
a = familystuff + 1;
}
You will get the desired output!!
There are several things wrong here:
myDaughter and myMum are different objects. You imply some kind of relationship between them, but there is none.
Your code has undefined behaviour, because your Daughter constructor uses the uninitialised member variable familystuff in an addition operation.
You should initialise your data members like this:
Mother::Mother() : motherstuff(0), familystuff(0), everyonesstuff(0) {}
Daughter::Daugher() : a(familystuff + 1) {}
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";
}
This one the question from my assignment i can't understand what it's mean can anyone help me out with this please?
Write a class that contains two class data members numBorn and numliving. The value of numBorn should be equal to the number of object of the class that have been instanced. The value of numLiving should be equal to the total number of objects in existence currently(i.e the object that have been constructed but not yet destructed.)
You'll need to make your variables static data members of your class. Then your constructor(s) and destructor will increment and decrement as needed.
class A
{
public:
static std::size_t numBorn;
static std::size_t numLiving;
A()
{
++numBorn;
++numLiving;
}
~A()
{
--numLiving;
}
};
std::size_t A::numBorn = 0;
std::size_t A::numLiving = 0;
As a small demo
int main()
{
A a1;
A a2;
{
A a3;
std::cout << "living: " << A::numLiving << " born: " << A::numBorn << '\n';
}
std::cout << "living: " << A::numLiving << " born: " << A::numBorn << '\n';
}
will output
living: 3 born: 3
living: 2 born: 3
Note that when a3 falls out of scope, the numLiving is decremented from its destructor.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
#include <iostream>
using namespace std;
class Fruit {
protected:
int nr_fruits = 0;
public:
void printTotal() {
cout << "Total fruits in the basket: " << nr_fruits << endl;
}
};
class Mango : public Fruit {
int nr_mangoes;
public:
void getMango(int x) {
nr_mangoes = x;
cout << "There are " << nr_mangoes << " mangoes in the basket" << endl;
nr_fruits = nr_fruits + nr_mangoes;
}
};
class Apple : public Fruit {
int nr_apples;
public:
void getApple(int x) {
nr_apples = x;
cout << "There are " << nr_apples << " apples in the basket" << endl;
nr_fruits = nr_fruits + nr_apples;
}
};
int main(int argc, const char * argv[]) {
Apple a1;
Mango m1;
a1.getApple(10);
a1.printTotal();
m1.getMango(20);
m1.printTotal();
return 0;
}
I need to make a function in the parent class Fruit, to be able to print the number of total fruits, in my case, nr_mangoes + nr_apples.
Obviously, the way i do it, the nr_fruits variable will output only the amount of mangoes or the amount of apples as the total amount of fruit.
How can i get to access the data members of the child classes, or make the variable nr_fruits so that it keeps the value throughout the program.
In this case you need the use of inheritance.
You will use virtual functions.
You will have to store in a vector of pointers to fruit, all the fruits you have.
vector<Fruit*> MyFruits;
Inside class Fruit you will implement a virtual function:
virtual int get_num_of_fruits(){}
And inside the child classes:
int get_num_of_fruits(){
return nr_child; //nr_apples,nr_mangos etc.
}
Then you will have an int nr_fruits = 0 and add to the number of all the fruits(apples,mangos etc.)
So, nr_fruits += MyFruits[i]->get_num_of_fruits(); for i = 0 to i<MyFruits.size()
In the case of your example and for simplicity, you can change your nr_fruits variable to be static, then initialize it after the class declaration:
class Fruit {
public:
static int nr_fruits;
void printTotal() {
cout << "Total fruits in the basket: " << nr_fruits << endl;
}
};
int Fruit::nr_fruits = 0;
However, without knowing the full scope of the requirements for your program, I think you may want to consider to design a better approach to your problem...
I have written a sample program.
If I print the address of pa and pb both are different.
Can you let me know why is this happening ?
#include<iostream>
using namespace std;
class A {
int x;
};
class B {
int y;
};
class C: public A, public B {
int z;
};
int main()
{
C c;
A *pa;
B *pb;
pa = &c;
pb = &c;
cout<<pa<<endl;
cout<<pb<<endl;
}
As Kerrek SB put it, pa and pb in your example don't actually point to c, but rather to the A and B subobjects of c.
With multiple inheritance, the data from the base classes is essentially stacked one after another. Base-typed pointers are simply offset to the data for that base class. Because of this, pa and pb point at different offsets into c.
#include<iostream>
using namespace std;
class A {
public:
int x;
};
class B {
public:
int y;
};
class C: public A, public B {
public:
int z;
};
int main()
{
C c;
cout << " &c: " << &c << endl << endl;
cout << "(A*)&c: " << (A*)&c << endl;
cout << "(B*)&c: " << (B*)&c << endl << endl;
cout << " &c.x: " << &c.x << endl;
cout << " &c.y: " << &c.y << endl;
cout << " &c.z: " << &c.z << endl << endl;
}
Result:
&c: 0x7ffdfeb26b20
(A*)&c: 0x7ffdfeb26b20
(B*)&c: 0x7ffdfeb26b24
&c.x: 0x7ffdfeb26b20
&c.y: 0x7ffdfeb26b24
&c.z: 0x7ffdfeb26b28
So you can see that C is laid out like this:
---------------
0x7ffdfeb26b20 | x | class A data
---------------
0x7ffdfeb26b24 | y | class B data
---------------
0x7ffdfeb26b28 | z | class C data
---------------
If you add some virtual methods to this example, you'll see that the same things happens with the subclass vtables.
--------- <------pa = &c
| x |
--------- <------pb = &c
| y |
---------
| z |
---------
it depends on the memory model of the class, above is an object of class C in memory
Back in the good old days of plain c, there were just structs.
struct Base{
int baseMember;
}
struct Child{
struct Base parent;
int someMoreMembers;
}
this way, dereferencing a pointer to a Child as if it were a base pointer, would result in a perfectly good pointer to the Base, because it is the first member.
In c++ this still works the same way (usually). But if you now inherit two classes, you cannot put them both as first member in your struct. So C++ converts a pointer to a base into a pointer to the child by adding the offset the specific base data is at.
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.