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.
Related
I am trying to develop a text adventure in C++ where users can input string commands (ex. "take apple").
Here is a very naive sample of code I came up with:
# include <iostream>
using namespace std;
class fruit{
public:
string actual_name;
fruit(string name){
actual_name = name;
}
take() {
cout << "You take a " << actual_name << "." << endl;
}
};
fruit returnObjectFromName(string name, fruit Fruits[]){
for(int i = 0; i <= 1; i++){ // to be modified in future depending on Fruits[] in main()
if (Fruits[i].actual_name == name)
return Fruits[i];
}
}
int main(){
string verb;
cout << "Enter verb: ";
cin >> verb;
string object;
cout << "Enter object: ";
cin >> object;
fruit apple("apple");
fruit Fruits[] = { apple }; // to be extended in future
// returnObjectFromName(object, Fruits). ??? ()
}
How can I possibly get the fruit method with something similar to the function returnObjectFromName, if this is even possible?
I began the development with Python (independently), and there I can at least use eval(), but as I understand in C++ this is not an option.
I tried also with map, but I didn't manage to make it work with methods.
Thank you all for your answers.
Its not good way to rely on reflection in C++ and i think there is no way to list methods in classes. Maybe you can use function pointers but pointer to instance methods are hell.
I recommend to use polymorphism and good design. If some items might be taken, then use interface like this:
#include <iostream>
using namespace std;
class ITakeable {
public:
virtual bool isTakeable() = 0;
virtual void take() = 0;
virtual void cannotTake() = 0;
};
class fruit : public ITakeable {
public:
string actual_name;
fruit(string name){
actual_name = name;
}
bool isTakeable() {
return true;
}
void take() {
cout << "You take a " << actual_name << "." << endl;
}
void cannotTake() {
cout << "not needed to be implemented";
}
};
class airplane : public ITakeable {
public:
string actual_name;
airplane(string name){
actual_name = name;
}
bool isTakeable() {
return false;
}
void take() {
cout << "not needed to be implemented";
}
void cannotTake() {
cout << "You CANNOT take a " << actual_name << "." << endl;
}
};
int main() {
fruit apple("apple");
if (apple.isTakeable()) {
apple.take();
}
airplane plane("boeing");
if (plane.isTakeable()) {
plane.take();
} else {
plane.cannotTake();
}
// use of interface in general
ITakeable * something = &apple;
if (something->isTakeable()) {
something->take();
}
something = &plane;
if (something->isTakeable()) {
something->take();
} else {
something->cannotTake();
}
return 0;
}
Since fruit is a user defined type, you have to declare your own methods for your type or you inherit from one previously defined.
There are a lot of method for "built-in" string type
that Performs virtually the same job as eval (...) in python.
Also I noticed your function need not be defined independently outside of class fruit.
I am working on a class assignment to create three classes nested inside each other. I need to make constructors and deconstructors for each that have a message that goes along with them. Finally, I need to create an instance of each class using new and call the display() function to show their message, followed by delete.
I have completed the assignment but in the wrong way, and I am confused about how I can properly put the code into the heap instead of the stack (as I was advised by my course tutor).
This is what I started with: (this code seems to work well, but does not fulfill the assigned project)
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
class Hen {
public:
Hen();
~Hen();
string display(void) {
return ("Im a Hen");
}
class Nest;
friend Nest;
class Nest {
public:
Nest();
~Nest();
string display(void) {
return ("Im a Nest");
}
class Egg;
friend Egg;
class Egg {
public:
Egg();
~Egg();
string display(void) {
return ("Im an egg");
}
};
};
};
Hen::Hen() {
cout << "I construct Hens" << endl;
}
Hen::~Hen() {
cout << "I deconstruct Hens" << endl;
}
Hen::Nest::Nest() {
cout << "I construct Nests" << endl;
}
Hen::Nest::~Nest() {
cout << "I deconstruct Nests" << endl;
}
Hen::Nest::Egg::Egg() {
cout << "I construct Eggs" << endl;
}
Hen::Nest::Egg::~Egg() {
cout << "I deconstruct Eggs" << endl;
}
int main() {
Hen hone;
Hen::Nest none;
Hen::Nest::Egg eone;
string h, n, e;
h = hone.display();
n = none.display();
e = eone.display();
cout << h << "\n" << n << "\n" << e << endl;
}
Where I am stuck is when I try to implement my code inside the heap, it seems to break by the second class:
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
class Hen {
public:
void display() {
cout << "Im a Hen" << endl;
}
class Nest;
friend Nest;
class Nest {
public:
void display() {
cout << "Im a Nest" << endl;
}
class Egg;
friend Egg;
class Egg {
public:
void display() {
cout << "Im an egg" << endl;
}
};
};
};
int main() {
Hen *hone = new Hen();
Hen::Nest *none = new Nest();
hone -> display();
none -> display();
}
Question 1:
If I remove all the information related to nest, the program runs Hen just fine and returns the "I'm a hen" statement. But, when I add in nest, the warning I recieve is
"error: expeected type-specifier before 'Nest'
Hen::Nest *none = new Nest();"
I do not understand what I am doing wrong as I did the exact same process for Hen and it worked. I do know that the error must be in the way Nest gets called through hen?
I apologize if this question is obvious, but I am just starting c++ and do not understand why I am getting these messages...
Thanks for your help!
I'm trying to understand virtual classes in C++. In Wikipedia, I found this example:
#include <iostream>
class Machine {
public:
void run() { }
class Parts {
public:
virtual int get_wheels() = 0;
virtual std::string get_fuel_type() = 0;
};
};
// The inner class "Parts" of the class "Machine" may return the number of wheels the machine has.
class Car: Machine {
public:
void run() {
std::cout << "The car is running." << std::endl;
}
class Parts: Machine::Parts {
public:
int get_wheels() override {
std::cout << "A car has 4 wheels." << std::endl;
return 4;
}
std::string get_fuel_type() override {
std::cout << "A car uses gasoline for fuel." << std::endl;
return "gasoline";
}
};
};
I can get the number of wheels of a car with:
Car::Parts c_p;
c_p.get_wheels();
Is there any other (simple) way? Is there any way instantiating only Car car ?
Update:
I understand the concerns, but I find it useful as a nested interface (with minimal changes):
#include <iostream>
#include <memory>
class Machine {
public:
virtual void run() = 0;
class Parts {
public:
virtual int get_wheels() = 0;
virtual std::string get_fuel_type() = 0;
};
};
class Car: public Machine {
public:
void run() {
std::cout << "The car is running." << std::endl;
}
class Parts: public Machine::Parts {
public:
int get_wheels() override {
std::cout << "A car has 4 wheels." << std::endl;
return 4;
}
std::string get_fuel_type() override {
std::cout << "A car uses gasoline for fuel." << std::endl;
return "gasoline";
}
};
};
int main () {
std::shared_ptr<Machine> X = std::make_shared<Car>();
(*X).run();
std::shared_ptr<Machine::Parts> Y = std::make_shared<Car::Parts>();
(*Y).get_wheels();
return 0;
}
I don't find any other code with this functionality. The only thing I miss is the possibility to access get_wheels directly from X. For instance, let's consider that I have a Machine in my program. The kind of machine I have will be specified dynamically. I want to know the number of wheels of this machine, but the method get_wheels must be inside a nested class Parts. The closer to solve this problem that I've got is with the code above, which gives me Machine and Machine::Parts as interfaces.
A simple solution would be to have a member part of you car:
struct Car : Machine {
struct Parts : Machine::Parts {
int get_wheels() override {
std::cout << "A car has 4 wheels." << std::endl;
return 4;
}
std::string get_fuel_type() override {
std::cout << "A car uses gasoline for fuel." << std::endl;
return "gasoline";
}
} parts; // <---
// or declare it as a separated member:
// Parts parts;
};
That way, you can call member functions like this:
Car car;
std::cout << car.parts.get_weels();
No. As it stands, a Car instance does not have any Car::Parts instances, nor any method that returns one.
The text around the example seems to be assuming that there is an instance of Machine::Parts associated with Machine somehow, which magically becomes a Car::Parts in Car. This may be the case in some other language, but it is not the case in C++.
A much more idomatic design would be to have a traits class template that Machine subclasses specialise.
template <typename Machine>
struct MachineParts;
template <>
struct MachineParts<Car> {
static int get_wheels() {
std::cout << "A car has 4 wheels." << std::endl;
return 4;
}
static std::string get_fuel_type() {
std::cout << "A car uses gasoline for fuel." << std::endl;
return "gasoline";
}
};
template <>
struct MachineParts<Bicycle> {
static int get_wheels() {
std::cout << "A bike has 2 wheels." << std::endl;
return 2;
}
static std::string get_fuel_type() {
std::cout << "A bike uses muscles for fuel." << std::endl;
return "muscles";
}
};
searched all over, Couldn't find answer I'm looking for w.r.t. unique_ptr. It's a problem I came across, couldn't solve it with unique_ptr, but I could do with traditional way.
I'm stuck with having array of pointers to abstract_base_class pointing to inherited class
Sorry posting whole code
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <memory>
using namespace std;
// Base is an abstract base class.
class Base {
private:
string myName; // Name of this person
public:
Base(string name) : myName(name) {}
// A pure virtual function with a function body
virtual void hello() const {
cout << "Hello, my name is " << myName
<< ". ";
}
};
class ServiceAgent : public Base {
public:
ServiceAgent(string name) : Base(name) {}
void hello() const {
Base::hello();
cout << "I'm a customer service representative. How may I help you?"
<< endl;
cout << "-----\n";
}
};
class Student : public Base {
public:
enum category { FRESHMAN, SOPHOMORE, JUNIOR, SENIOR };
category personType;
Student(string name, category pType) : Base(name) {
personType = pType;
}
void hello() const {
string tmp = enumToString(personType);
Base::hello();
cout << tmp << endl;
cout << "-----\n";
}
string enumToString (category c) const
{
string s;
switch (c) {
case FRESHMAN:
s = "I'm a Freshman";
break;
case SOPHOMORE:
s = "I'm a Sophomore";
break;
case JUNIOR:
s = "I'm a Junior";
break;
case SENIOR:
s = "I'm a Senior";
break;
default:
s = "none";
break;
}
return s;
}
};
class CSStudent : public Student {
public:
CSStudent(string name, Student::category type) : Student(name, type) {}
void hello() const {
Base::hello();
cout << "I'm a computer science major.\n";
cout << "-----\n";
}
};
class BUSStudent : public Student {
public :
BUSStudent(string name, Student::category type) : Student(name, type) {}
void hello() {
Base::hello();
cout << "I'm a business major.\n";
cout << "-----\n";
}
};
int main() {
ServiceAgent *agentJack = new ServiceAgent("Jacqueline");
Student *studentJack = new Student("Jackson", Student::FRESHMAN);
CSStudent *studentCSS = new CSStudent("Jack", Student::SOPHOMORE);
BUSStudent *studentBus1 = new BUSStudent("Jacky", Student::JUNIOR);
BUSStudent *studentBus2 = new BUSStudent("Joyce", Student::SENIOR);
Base *arr[] = { agentJack, studentJack, studentCSS, studentBus1, studentBus2};
for (Base *var : arr)
{
var->hello();
}
unique_ptr<ServiceAgent> u_agentJack(new ServiceAgent("Jacqueline"));
unique_ptr<Student> u_studentJack(new Student("Jackson", Student::FRESHMAN));
unique_ptr<CSStudent> u_studentCSS(new CSStudent("Jack", Student::SOPHOMORE));
unique_ptr<BUSStudent> u_studentBus1(new BUSStudent("Jacky", Student::JUNIOR));
unique_ptr<BUSStudent> u_studentBus2(new BUSStudent("Joyce", Student::SENIOR));
//unique_ptr<Base*> ptr ; //(new Base*);//{ u_agentJack, u_studentJack, u_studentCSS, u_studentBus1, u_studentBus2 };
//ptr = static_cast<unique_ptr<Base*>>u_agentJack;
return 0;
}
I tried these, doesn't work.
unique_ptr<Base*> ptr (new (Base*[5] { u_agentJack, u_studentJack, u_studentCSS, u_studentBus1, u_studentBus2 });
tried with single entry
//ptr = static_cast<unique_ptr<Base*>>u_agentJack;
Change std::unique_ptr<Base*> to std::unique_ptr<Base>, and add a virtual destructor to Base. Then you can declare an array of unique_ptr<Base> objects the same way you declare an array of Base* pointers, and std::move() your existing std::unique_ptr objects into the array.
Try this:
#include <iostream>
#include <string>
#include <memory>
using namespace std;
// Base is an abstract base class.
class Base {
private:
string myName; // Name of this person
public:
Base(string name) : myName(name) {}
virtual ~Base() {}
// A pure virtual function with a function body
virtual void hello() const {
cout << "Hello, my name is " << myName << ".";
}
};
class ServiceAgent : public Base {
public:
ServiceAgent(string name) : Base(name) {}
void hello() const override {
Base::hello();
cout << " I'm a customer service representative. How may I help you?" << endl;
}
};
class Student : public Base {
public:
enum category { FRESHMAN, SOPHOMORE, JUNIOR, SENIOR };
category personType;
Student(string name, category pType) : Base(name), personType(pType) {}
void hello() const override {
Base::hello();
cout << " " << enumToString(personType) << endl;
}
string enumToString (category c) const
{
switch (c) {
case FRESHMAN:
return "I'm a Freshman";
case SOPHOMORE:
return "I'm a Sophomore";
case JUNIOR:
return "I'm a Junior";
case SENIOR:
return "I'm a Senior";
}
return "";
}
};
class CSStudent : public Student {
public:
CSStudent(string name, Student::category type) : Student(name, type) {}
void hello() const override {
Student::hello();
cout << "I'm a computer science major." << endl;
}
};
class BUSStudent : public Student {
public :
BUSStudent(string name, Student::category type) : Student(name, type) {}
void hello() const override {
Student::hello();
cout << "I'm a business major." << endl;
}
};
int main() {
std::unique_ptr<ServiceAgent> agentJack(new ServiceAgent("Jacqueline"));
std::unique_ptr<Student> studentJack(new Student("Jackson", Student::FRESHMAN));
std::unique_ptr<CSStudent> studentCSS(new CSStudent("Jack", Student::SOPHOMORE));
std::unique_ptr<BUSStudent> studentBus1(new BUSStudent("Jacky", Student::JUNIOR));
std::unique_ptr<BUSStudent> studentBus2(new BUSStudent("Joyce", Student::SENIOR));
std::unique_ptr<Base> arr[] = { std::move(agentJack), std::move(studentJack), std::move(studentCSS), std::move(studentBus1), std::move(studentBus2) };
for (auto &var : arr)
{
var->hello();
cout << "-----" << endl;
}
return 0;
}
Live Demo
I stumbled across this piece of code when I researched for a good example for Observer Design pattern. In main, it gets error, taking address of temporary[-fpermissive] which I dont dont understand what it is frankly. Sending a class refference to an function? Is this real life?
#include <vector>
#include <iostream>
using namespace std;
class AlarmListener
{
public:
virtual void alarm() = 0;
};
class SensorSystem
{
vector < AlarmListener * > listeners;
public:
void attach(AlarmListener *al)
{
listeners.push_back(al);
}
void soundTheAlarm()
{
for (int i = 0; i < listeners.size(); i++)
listeners[i]->alarm();
}
};
class Lighting: public AlarmListener
{
public:
/*virtual*/void alarm()
{
cout << "lights up" << '\n';
}
};
class Gates: public AlarmListener
{
public:
/*virtual*/void alarm()
{
cout << "gates close" << '\n';
}
};
class CheckList
{
virtual void localize()
{
cout << " establish a perimeter" << '\n';
}
virtual void isolate()
{
cout << " isolate the grid" << '\n';
}
virtual void identify()
{
cout << " identify the source" << '\n';
}
public:
void byTheNumbers()
{
// Template Method design pattern
localize();
isolate();
identify();
}
};
// class inheri. // type inheritance
class Surveillance: public CheckList, public AlarmListener
{
/*virtual*/void isolate()
{
cout << " train the cameras" << '\n';
}
public:
/*virtual*/void alarm()
{
cout << "Surveillance - by the numbers:" << '\n';
byTheNumbers();
}
};
int main()
{
SensorSystem ss;
ss.attach(&Gates());
ss.attach(&Lighting());
ss.attach(&Surveillance());
ss.soundTheAlarm();
}
This is ill-formed:
ss.attach(&Gates());
^^^
Gates() is an rvalue (specifically, a prvalue). You cannot take the address of an rvalue. It's not an object that has identity, so it doesn't really have an address that you can take. The language is preventing you from doing something that doesn't make sense to do. If you did store a pointer to this temporary, you'd just end up with a dangling pointer since at the end of this line the temporary Gates would be destroyed.
Since SensorSystem doesn't own its AlarmListeners, you'll have to create them up front:
Gates gates;
Lighting lighting;
Surveillance surveillance;
SensorSystem ss;
ss.attach(&gates);
ss.attach(&lighting);
ss.attach(&surveillance);