I have a challenge for the school that states
Define a member function PrintAll() for class PetData that prints output as follows. Hint: Make use of the base class's PrintAll() function.
Name: Fluffy, Age: 5, ID: 4444
Then they give me the code below with a small snippet that I can alter. Between
// FIXME: Add PrintAll() member function
and
/* Your solution goes here */
is the code I added but I'm not getting the correct result.
MyCode
// FIXME: Add PrintAll() member function
void PrintAll() {
AnimalData data;
data.PrintAll();
cout << ", ID: " << idNum;
}
/* Your solution goes here */
Full Code
#include <iostream>
#include <string>
using namespace std;
class AnimalData {
public:
void SetName(string givenName) {
fullName = givenName;
};
void SetAge(int numYears) {
ageYears = numYears;
};
// Other parts omitted
void PrintAll() {
cout << "Name: " << fullName;
cout << ", Age: " << ageYears;
};
private:
int ageYears;
string fullName;
};
class PetData: public AnimalData {
public:
void SetID(int petID) {
idNum = petID;
};
// FIXME: Add PrintAll() member function
void PrintAll(){
AnimalData data;
data.PrintAll();
cout << ", ID: " << idNum;
}
/* Your solution goes here */
private:
int idNum;
};
int main() {
PetData userPet;
userPet.SetName("Fluffy");
userPet.SetAge (5);
userPet.SetID (4444);
userPet.PrintAll();
cout << endl;
return 0;
}
Results I'm getting
Name: , Age: -502747520, ID: 4444
Results I want
Name: Fluffy, Age: 5, ID: 4444
in
void PrintAll(){
AnimalData data;
data.PrintAll();
cout << ", ID: " << idNum;
}
AnimalData data; creates a new, default-initialized AnimalData that is entirely separate from the AnimalData that is part of the current PetData. Since you want to use the AnimalData you already have, discard this line and remove data from the next. This is where things can go very wrong, so I'm going to skip directly to the correct answer: To get the PrintData function for AnimalData, you need to be explicit:
void PrintAll(){
AnimalData::PrintAll();
cout << ", ID: " << idNum;
}
Why You Cannot Simply Remove data
If you remove the object to invoke PrintAll on, data,
void PrintAll(){
PrintAll();
cout << ", ID: " << idNum;
}
this is assumed. this is a PetData, and for PetData the best match for the PrintAll function is the current function. The result is infinite recursion.
The real lesson to be learned here is to be careful when re-using an identifier. In this case, PetData::PrintAll shadows AnimalData::PrintAll, replacing it inside PetData. The function is not virtual, and you do not want virtual in this case, so you do not get an override. You can easily and accidentally do this with functions and variables, leading to confusion about which one is being used by the program.
A (possibly) Better Way to Structure This Program
Take advantage of both inheritance and polymorphism
#include <iostream>
#include <string>
using namespace std;
class AnimalData
{
public:
virtual ~AnimalData() {}; // with polymorphism you must make sure the
// correct destructor is always called.
// Derived classes will override this
// destructor whether you explicitly define
// them or not.
void SetName(string givenName)
{
fullName = givenName;
}
void SetAge(int numYears)
{
ageYears = numYears;
}
// virtual function. Derived classes can, but do not have to, replace
// this function with a version better suited to the derived class
virtual void PrintAll()
{
cout << "Name: " << fullName;
cout << ", Age: " << ageYears;
}
private:
int ageYears;
string fullName;
};
class PetData: public AnimalData
{
public:
void SetID(int petID)
{
idNum = petID;
}
// Replacing virtual function. Note if the base class function is
// virtual, then child class overrides are automatically virtual
void PrintAll() override // override keyword notifies with a compiler
// error if the function does NOT override when
// it should.
{
AnimalData::PrintAll(); // call base class version for basic data
cout << ", ID: " << idNum; // adding derived class-specific stuff
}
private:
int idNum;
};
// can add WildData here to handle wild animals.
int main()
{
PetData userPet;
userPet.SetName("Fluffy");
userPet.SetAge(5);
userPet.SetID(4444);
userPet.PrintAll();
cout << endl;
// add an vanilla animal for demo
AnimalData generic;
generic.SetName("Fang");
generic.SetAge(7);
generic.PrintAll();
cout << endl;
// demonstrate polymorphism
AnimalData * ptr = & generic;
ptr->PrintAll();
cout << endl;
ptr = & userPet;
ptr->PrintAll(); // runtime calls the correct PrintAll function
cout << endl;
return 0;
}
You appear to have a small misunderstanding about how to invoke methods of the superclass AnimalData in PetData:
void PrintAll(){
AnimalData data;
data.PrintAll();
cout << ", ID: " << idNum;
}
This creates a new instance of the class AnimalData, and invokes PrintAll() on that object. Because the fullName and ageYears aren't initialised in this new object, you get the unexpected output. To invoke the same method of the superclass, the syntax is Superclass::Methodname(). So the correct version of AnimalData::PrintAll() is as follows:
void PrintAll(){
AnimalData::PrintAll();
cout << ", ID: " << idNum;
}
Here's your problem.
void PrintAll(){
AnimalData data;
data.PrintAll();
cout << ", ID: " << idNum;
}
This function creates a new object of class AnimalData (which will be constructed according to the default constructor) and then calls the AnimalData::PrintAll method on that object. What you wanted to do was call the AnimalData::PrintAll method on this object.
void PrintAll(){
AnimalData::PrintAll(); // call base class method
cout << ", ID: " << idNum;
}
So this one was alot simpler than I thought. It's really a matter of calling the printAll method from PetData, and appending the ID num.
public void printAll(){
super.printAll();
System.out.print(", ID: " + idNum);
}
Related
Hi StackOverflow community!
I'm expecting different outputs depending on the class of object to be printed but that's not the case.
Medium.h
#include "Datum.h"
#include "Person.h"
class Medium
{
public:
Medium(std::string initTitel);
virtual ~Medium(void);
void ausgabe() const;
bool ausleihen(Person person, Datum ausleihdatum);
void zurueckgeben();
unsigned int getID();
protected:
static unsigned int currentID;
unsigned int ID;
std::string titel;
bool status;
Datum datumAusgeliehen;
Person personAusgeliehen;
};
Medium.cpp
#include "Medium.h"
#include <string>
#include <iostream>
unsigned int Medium::currentID = 1;
Medium::Medium(std::string initTitel): titel(initTitel), status(false)
{
ID = currentID++;
}
Medium::~Medium(void) {}
void Medium::ausgabe() const
{
std::cout << "ID: " << ID << std::endl;
std::cout << "Titel: " << titel << std::endl;
switch (status)
{
case true:
std::cout << "Status : Das Medium ist seit dem "
<< datumAusgeliehen << " an "
<< personAusgeliehen.getName() << " ausgeliehen."
<< std::endl;
break;
case false:
std::cout << "Status: Medium ist zurzeit nicht verliehen." << std::endl;
break;
}
}
The function prints ID, title and status to console.
Now depending on the type of Medium, I would like to print extra information using the function void ausgabe() const.
Example: If the Medium is a book(in german buch = book), information about author should be printed, in addition to other information available in Medium class. i.e, I have got the subclass called Buch which also has an void ausgabe() const function, which should print this extra information in class Buch.
Buch.h
#include "Medium.h"
class Buch: public Medium
{
public:
Buch();
Buch(std::string initTitel, std::string initAutor);
virtual ~Buch();
void ausgabe() const;
private:
std::string autor;
};
Buch.cpp
#include "Buch.h"
Buch::Buch(std::string initTitel, std::string initAutor): Medium(initTitel), autor(initAutor)
{ // TODO Auto-generated constructor stub }
Buch::~Buch() { // TODO Auto-generated destructor stub }
void Buch::ausgabe() const
{
Medium::ausgabe();
std::cout << "Autor: " << autor << std::endl;
}
As far as I have: In the class Buch, while calling the output function ausgabe() the extra information autor will be printed automatically. But for the remaining informations from Medium class, could you help. Thanks for your help :)
Now depending on the type of Medium to be printed, I would like to add
extra information to be printed. E.g. if the Medium is a book,
information about author should be printed too.
So you are looking for dynamic-polymorphism. Then, you need to make void ausgabe()const function to virtual in your base class(Medium), in order to call it polymorphically. And you need to override it in other subclasses(for instance class Buch). In the given code anyways these are not there. In addition to that, you also need virtual destructor at your base class.
Then in your class Buch's ausgabe() should be:
void ausgabe()const override
{
Medium::ausgabe(); // call first base class's ausgabe()
std::cout << "autor :" << autor << std::endl;
}
Then in your main, you can do this: See an example code here
int main ()
{
std::unique_ptr<Medium> some_objects[2];
some_objects[0] = std::make_unique<Medium>("Some Title");
some_objects[1] = std::make_unique<Buch>("Title 2", "user9775960");
for(auto& obj_type: some_objects)
obj_type->ausgabe();
return 0;
}
PS: always try to post English written code in the community, so that everybody can follow.
I am working on an assignment using sub classes demonstrating polymorphism. This program requires a name to be given for each of the new objects. I am only supposed to have string getName(){return name;} (this is located in the base class). There is also a constructor in each of the classes class(string){}. In the main function I want to set the name for each of the objects. Any advice is much appreciated in how I should do so!
h file:
#ifndef DUCK_H
#define DUCK_H
#include <string>
using namespace std;
class Duck
{
private:
string name;
public:
Duck(){}
Duck(string){}
string getName() { return name; };
virtual string quack() {return "Which"; }
virtual string fly() { return "How?"; }
};
class RubberDuck : public Duck
{
public:
RubberDuck(){}
RubberDuck(string) {}
string quack() { return "Squeak"; }
string fly() { return "Fly with bounce"; }
};
class MallardDuck : public Duck
{
public:
MallardDuck(){}
MallardDuck(string) {}
string quack() { return "Quack"; }
string fly() { return "Fly with wings"; }
};
class RocketDuck : public Duck
{
public:
RocketDuck(){}
RocketDuck(string) {}
string quack() { return "Zoom"; }
string fly() { return "Fly with rockets"; }
};
#endif // !1
cpp file:
#include <iostream>
#include "Duck.h"
using namespace std;
//void display(Duck *d);
int main()
{
Duck d1;
MallardDuck md;
RubberDuck rbd;
RocketDuck rd;
//for main duck
//Duck duck("Donald");
//cout << duck.getName();
cout << d1.quack() <<"\n";
cout << d1.fly() <<"\n";
cout << "\n";
//for rubber duck
RubberDuck rbdname("Rubby");
cout << rbd.quack() << "\n";
cout << rbd.fly() << "\n";
cout << "\n";
//for mallard duck
MallardDuck mdname("Mally");
cout << md.quack() << "\n";
cout << md.fly() << "\n";
cout << "\n";
// for rocket duck
RocketDuck rdname("Rocky");
cout << rd.quack() << "\n";
cout << rd.fly() << "\n";
cout << "\n";
//polymorphism
Duck *d2 = new MallardDuck();
cout << d2->getName() << "\n";
cout << d2->quack() << "\n";
cout << d2->fly() << "\n";
cout << "\n";
return 0;
}
/*void display(Duck d)
{
cout << d.quack();
}
*/
Are you asking how to call the constructor you've defined? You would do that like
Duck duck("Drake Mallard");
With this code:
Duck(){}
Duck(string){}
You don't initialize your member name, whether you call the default constructor or the string one.
You have to use the input parameter like I showed you:
Duck(string const & input_name) : name(input_name) {}
^^^^^^^^^^^^^^^^
The underlined part initializes your member name to the value "Drake Mallard" when you do:
Duck duck("Drake Mallard");
Then, you will have duck.getName() returning "Drake Mallard".
And you have to apply the same principle in your derived classes, to call this very same base constructor:
class RubberDuck : public Duck
{
public:
RubberDuck() : Duck("RubberDuck") {}
RubberDuck(string const & input_name) : Duck(input_name) {}
Then
RubberDuck rubber; // name = "RubberDuck"
RubberDuck rubber("Ruber"); // name = "Rubber"
But also:
RubberDuck * rubber = new RubberDuck(); // name = "RubberDuck"
RubberDuck * rubber = new RubberDuck("Ruber"); // name = "Rubber"
If you ask, the front part Duck:: in my comment considered you where implementing your constructor outside of class Duck { ... };.
You should avoid using namespace, especially within headers.
My task was to create an object in class, initialize it and output(using pointer to class). This code compiles perfectly, but the output doesn't appear. I would really appreciate any help, thank you in advance!
#include <iostream>
#include <string>
using namespace std;
class family
{
public:
void setWife(string w)
{w = wife;};
string getWife()
{return wife;};
void setHusband(string h)
{husband = h;};
string getHusband()
{return husband;};
void setSon(string s)
{s = son;};
string getSon()
{return son;};
void setDaughter1(string d1)
{d1 = daughter1;};
string getDaughter1()
{return daughter1;};
void setDaughter2(string d2)
{daughter2 = d2;};
string getDaughter2()
{return daughter2;};
double* getPointer()
{return &pointer;};
void initialize()
{
setWife("Shirley Collin");
setHusband("Donald Collin");
setSon("Collin Collin");
setDaughter1("Harriet Collin");
setDaughter2("Hillary Collin");
}
friend void output(family* Collin);
private:
string wife;
string husband;
string son;
string daughter1;
string daughter2;
double pointer;
};
void output(family* Collin)
{cout << "Husband is " <<Collin->getHusband()<< endl;
cout << "wife is " << Collin ->getWife() << endl;
cout << "son is " << Collin->getSon() << endl;
cout << "daughter1 is " << Collin->getDaughter1() << endl;
cout << "daughter2 is " << Collin->getDaughter2()<< endl;
};
int main()
{family Collin;
Collin.initialize();
family *pointer = new family;
output (pointer);
cin.ignore();
}
family Collin;
Collin.initialize();
This constructs an instance of the family class, and initializes it with the values defined in the initialize() method.
family *pointer = new family;
output (pointer);
This constructs a second instance of the family class, does not initialize it in any way, and calls the output() method, to display the contents of the completely uninitialized second instance of this family class.
This is why this program produces no useful output.
You probably want to replace these four lines with:
family *pointer=new family;
pointer->initialize();
output(pointer);
I've been working on this assignment for a while. Here's the instructions:
You are to design an abstract class called Employee whose members are
as given below (make them protected):
Data members: char *name, long int ID
Two constructors: A Default constructor // intitialize data memebrs to
the default values and a copy constructor
Methods: setPerson (char *n, long int id) //allows user to set
information for each person A function called Print () // should be a
virtual function, that prints the data attributes of the class. and a
destructor
Also define two classes that derived from class Employee, called
Manager and Secretary. Each class should inherit all members from the
base class and has its own data members and member functions as well.
The Manager should have a data member called degree for his/her
undergraduate degree (e.g. diploma, bachelor, master, doctor), the
Secretary should have her contract (can be a Boolean value 1/0 for
permanent/temporary).
All member functions of derived class should be overrided from their
base class.
Write the following main() to test your classes
int main() {
Employee * p = new Manager(“Bruce Lee”, 0234567, “Dr.”);
P.print();
Secretary p2;
p2.setPerson(“Wilma Jones”, 0341256, “permanent”);
delete p;
p = & p2;
p.Print();
return 0;
}
This is everything I've come up with so far, but I'm pretty sure it's riddled with mistakes and that my arguments and variable types are all off.
#include <iostream>
using namespace std;
class Employee{
protected:
char *name;
long int ID;
public:
Employee();
Employee(Employee&);
void setPerson(char * n, long int eID) {
name = n;
ID = eID; };
virtual void Print(){
cout << "Name: " << name << endl;
cout << "ID: " << ID << endl; };
};
class Manager: public Employee {
protected:
char *degree;
public:
void setPerson(char * n, long int eID, char * d){
name = n;
ID = eID;
degree = d;
};
void Print() {
cout << "Name: " << name << endl;
cout << "ID: " << ID << endl;
cout << "Degree: " << degree << endl;
};
};
class Secretary: public Employee {
protected:
bool contract;
public:
void setPerson(char * n, long int eID, string c){
name = n;
ID = eID;
if (c == "permanent") contract = true;
else contract = false;
};
void Print(){
cout << "Name: " << name << endl;
cout << "ID: " << ID << endl;
cout << "Contract: " << contract << endl;
};
};
int main() {
Employee * P = new Manager("Bruce Lee", 0234567, "Dr.");
P.Print();
Secretary P2;
P2.setPerson("Wilma Jones", 0341256, "permanent");
delete P;
P = & P2;
P.Print();
return 0;
}
I'm getting an error on line 62 (the first line of the main code):
No matching constructor for initialization of Manager
I've tried reading similar questions, but they haven't helped me much. I think the most confusing thing is contract being a bool value and the use of char arguments. Any guidance at all is appreciated.
The error you're getting is pretty straight-forward: you don't have any constructor for Manager (or Employee) that takes a string, integer (?), and string as arguments.
You have declared the constructor employee but not defined it.
Look at the class employee, Under publc you have declared
Employee();
Employee(Employee&);
But you have not defined the function. You need
Employee :: Employee()
{
bla bla bla
}
and another one for the other signature.
#include <iostream>
using namespace std;
class Machine
{
class State *current;
public:
Machine();
void setCurrent(State *s)
{
current = s;
}
void on();
void off();
};
class State
{
public:
virtual void on(Machine *m)
{
cout << " already ON\n";
}
virtual void off(Machine *m)
{
cout << " already OFF\n";
}
};
void Machine::on()
{
current->on(this);
}
void Machine::off()
{
current->off(this);
}
class ON: public State
{
public:
ON()
{
cout << " ON-ctor ";
};
~ON()
{
cout << " dtor-ON\n";
};
void off(Machine *m);
};
class OFF: public State
{
public:
OFF()
{
cout << " OFF-ctor ";
};
~OFF()
{
cout << " dtor-OFF\n";
};
void on(Machine *m)
{
cout << " going from OFF to ON";
m->setCurrent(new ON());
delete this;
}
};
void ON::off(Machine *m)
{
cout << " going from ON to OFF";
m->setCurrent(new OFF());
delete this;
}
Machine::Machine()
{
current = new OFF();
cout << '\n';
}
int main()
{
void(Machine:: *ptrs[])() =
{
Machine::off, Machine::on
};
Machine fsm;
int num;
while (1)
{
cout << "Enter 0/1: ";
cin >> num;
(fsm. *ptrs[num])();
}
}
There are a few bits of code I don't completely understand.
First, what does this do exactly?
(fsm. *ptrs[num])();
It looks like it's calling a default constructor of state, but I am not totally sure. Also, I don't understand where the on and off method is called. I think the object machine is the calling object for the on and off method, but I am not even sure.
Lastly, why do we destroy this?
void on(Machine *m)
{
cout << " going from OFF to ON";
m->setCurrent(new ON());
delete this;
}
Is it only for memory management?
I have rewritten the code with two function pointers and some comments:
Instead of array of function pointers, I have used 2 diff pointers and I am using if else for making the decision for switching state.
Main:
int main()
{
void (Machine::*offptr)() = &Machine::off; //offptr is a member funct pointer that now points to Machine::off function
void (Machine::*onptr)() = &Machine::on; //onptr is a member funct pointer that now points to Machine::on function
Machine fsm;
int num;
while (1)
{
cout<<"Enter 0/1: ";
cin>>num;
if( num == 0 )
{
(fsm.*offptr)(); //Here your are calling the function pointed to by the offptr (i.e., Machine::off) using the pointer
}
else if( num == 1 )
{
(fsm.*onptr)(); //Here your are calling the function pointed to by the onptr (i.e., Machine::on) using the pointer
}
}
}
In your example, all the decision is taken with the help of pointer array indices it self. So if user presses 0 the function pointed by ptrs[0] will be called and for 1 the function pointed by ptr[1] will be called. But since there is no check to make sure the user entered 0/1, the program will crash if the user enters something other than 0 or 1.
void on(Machine *m)
{
cout << " going from OFF to ON";
m->setCurrent(new ON()); //Here you are changing the state of the machine from OFF to ON (Note: call comes to this function only if the previous state was OFF).
delete this; //The previous state instance (OFF state pointed by this pointer) of the machine is no more required. So you are deleting it.
}