I have this UML Diagram and I have written the code below but I am struggling with an error message
However, while compiling and linking, I got an error
/tmp/cc9oQaPX.o: In function `main':
main.cpp:(.text+0x8c): undefined reference to `Fish::Fish(std::string)'
main.cpp:(.text+0xe5): undefined reference to `Cat::Cat(std::string)'
main.cpp:(.text+0x116): undefined reference to `Fish::Fish()'
main.cpp:(.text+0x158): undefined reference to `Cat::Cat()'
collect2: error: ld returned 1 exit status
#include <iostream>
using namespace std;
class Animal // define base class
{
protected:
int legs; // base class properties
public:
Animal(int legNumbers) // set values of leg
{
legNumbers = legs; // set values of leg
}
virtual void eat() = 0; // method of base class
virtual void walk() {}; // method of base class
};
class Pet // define the pet class
{
protected:
string name; // set properties of pet class
public:
virtual string getName(); // define method
virtual string setName(string name); // set name values
virtual void play() // define play method
{
cout << " garfield is playing now." << endl; // out values
}
};
class Spider :public Animal //child class inherit base class
{
public:
Spider() :Animal(8) // spider class inherit animal class
{
cout << "animals with " << legs << " legs is walking. " << endl;
}
virtual void eat() // define virtual method
{
cout << "spider is eating now. " << endl;
}
};
class Cat :public Pet, public Animal // cat inherit two classes
{
public:
Cat(string name); // set name method
Cat();
virtual void play() // define method
{
cout << name << " is playing now. " << endl;
}
virtual void eat(); // define method here
};
class Fish : public Pet, public Animal // fish inherit two method
{
public: // define public members
Fish(string name);
Fish();
virtual void play()
{
cout << name << " is playing now. " << endl;
}
virtual void eat(); // method here
void walk()
{
cout << " Fish cannot walk " << endl; // output the values
}
};
string Pet::getName() // get name value from parent class
{
return string();
}
string Pet::setName(string name)
{
return string();
}
int main(int argc, char* argv[]) // define main method
{
Fish* f = new Fish("Jaws");
Cat* c = new Cat("Tenkir");
Animal *a = new Fish();
Animal* e = new Spider();
Pet* p = new Cat();
f->play();
c->play();
e->eat();
e->walk();
a->walk();
p->play();
return 0;
}
This is right code.
Firstly, you didn't defined the constructors for Cat an Fish
But that wasn't the only problem.
Your functions walk, eat, play need to be override. And eat() has to have a block, becuase in the base class (Animal) is deleted, like eat() = 0;
#include <iostream>
using namespace std;
class Animal // define base class
{
protected:
int legs; // base class properties
public:
Animal(int legNumbers) // set values of leg
{
legs = legNumbers; // set values of leg
}
virtual ~Animal() {}
virtual void eat() = 0; // method of base class
virtual void walk() {}; // method of base class
};
class Pet // define the pet class
{
protected:
string name; // set properties of pet class
public:
virtual string getName(); // define method
virtual void setName(string name); // set name values
virtual void play() // define play method
{
cout << " garfield is playing now." << endl; // out values
}
};
string Pet::getName() // get name value from parent class
{
return this->name;
}
void Pet::setName(string name)
{
this->name = name;
}
class Spider :public Animal //child class inherit base class
{
public:
Spider() :Animal(8) // spider class inherit animal class
{
cout << "animals with " << legs << " legs is walking. " << endl;
}
virtual void eat() // define virtual method
{
cout << "spider is eating now. " << endl;
}
};
class Cat :public Pet, public Animal // cat inherit two classes
{
public:
Cat(string name)
:Animal(4)
{
this->setName(name);
} // set name method
Cat():Animal(4){}
~Cat() override {}
virtual void play() override // define method
{
cout << name << " is playing now. " << endl;
}
virtual void eat() override {} // define method here
};
class Fish : public Pet, public Animal // fish inherit two method
{
public: // define public members
Fish(string name)
:Animal(0)
{
this->setName(name);
}
Fish():Animal(0){}
~Fish() override {}
virtual void play() override
{
cout << name << " is playing now. " << endl;
}
virtual void eat() override {} // method here
void walk() override
{
cout << " Fish cannot walk " << endl; // output the values
}
};
int main(int argc, char* argv[]) // define main method
{
Fish* f = new Fish("Jaws");
Cat* c = new Cat("Tenkir");
Animal *a = new Fish();
Animal* e = new Spider();
Pet* p = new Cat();
f->play();
c->play();
e->eat();
e->walk();
a->walk();
p->play();
return 0;
}
Related
I am trying to do something like this:
class Movement {
public:
virtual void move() = 0;
};
class Walk : public Movement {
public:
void move() { cout << "walking"; }
};
class Run : public Movement {
public:
void move() { cout << "run"; }
};
class Animal {
public:
virtual void print();
};
class Human : public Animal {
public:
void print() { cout << "Human"; }
};
class Lion : public Animal {
public:
void print() { cout << "Lion"; }
};
class Model {
Animal* animal;
Movement* movement;
public:
Model(Animal* animal = new Human(), Movement* movement = new Walk()) {
this->animal = animal;
this->movement = movement;
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first = Model(), second = Model(new Lion(), new Run());
first.print();
cout << endl;
second.print();
return 0;
}
How do we set the default value for abstract class pointers & how to pass them as a parameter like that from main?
I would also prefer to be able to pass arguments from main like this only in a single line without needing to initialize before.
can anyone please help me with how do we such things in C++?
I have tried and searched a lot but no luck.
I am looking for a workaround to do something like this, in which we use an abstract classes as a parameter of other classes.
I know objects cannot be assigned to a pointer, I just don't know what to do there to fulfill my requirement, an abstract class as a parameter with a default value.
This is my latest attempt with exact code, but unfortunately with new, does anyone know how to get rid of new and achieve the desired outcome?
Note:
My actual code is quite complex, basically using an abstract class for polymorphism and pass those abstract classes as parameters to another class with default parameters, if there is ANY other way to do something similar I would really appreciate the help.
This is really a design question. In Modelclass design, you either need to decide about the object ownership, or defer the decision to the calling code. In the latter case, you cannot have default arguments (unless you want to have global constants Human and Walk, but I would not recommend it).
One way to have the default arguments is to decide that Model has exclusive ownership of Animal and Movement, and store unique_ptrs to them. Something like this:
class Model {
unique_ptr<Animal> animal;
unique_ptr<Movement> movement;
public:
Model(unique_ptr<Animal> animal = make_unique<Human>(), unique_ptr<Movement> movement = make_unique<Walk>()){
this->animal = std::move(animal);
this->movement = std::move(movement);
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first/*no () here!*/, second(make_unique<Lion>(), make_unique<Run>());
first.print();
cout << endl;
second.print();
return 0;
}
I think I came up with the best solution for my situation.
#include <iostream>
#include <memory>
using namespace std;
class Movement {
public:
virtual void move() = 0;
virtual unique_ptr<Movement> movement() const = 0;
};
class Walk : public Movement {
public:
void move() { cout << "walking"; }
unique_ptr<Movement> movement() const { return make_unique<Walk>(); }
};
class Run : public Movement {
public:
void move() { cout << "run"; }
unique_ptr<Movement> movement() const { return make_unique<Run>(); }
};
class Animal {
public:
virtual void print() = 0;
virtual unique_ptr<Animal> animal() const = 0;
};
class Human : public Animal {
public:
void print() { cout << "Human"; }
unique_ptr<Animal> animal() const { return make_unique<Human>(); }
};
class Lion : public Animal {
public:
void print() { cout << "Lion"; }
unique_ptr<Animal> animal() const { return make_unique<Lion>(); }
};
class Model {
unique_ptr<Animal> animal;
unique_ptr<Movement> movement;
public:
Model(const Animal& animal = Human(), const Movement& movement = Walk()) {
this->animal = animal.animal();
this->movement = movement.movement();
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first = Model(), second = Model(Lion(), Run());
first.print();
cout << endl;
second.print();
return 0;
}
Is your problem the compile error? There are multiple ways to address the compile error, but given that your question is about inheriting from abstract classes, I will focus on that.
First, as provided, your Animal class is not an abstract class. An abstract class cannot be instantiated because all its methods are pure virtual. In C++, pure virtual functions are designated by the virtual keyword prefix, and suffixed by = 0 in their definition. E.g.
...
virtual void print() = 0;
...
The following code is compilable by making your Animal class an abstract class:
#include <iostream>
using namespace std;
class Movement {
public:
virtual void move() = 0;
};
class Walk : public Movement {
public:
void move() { cout << "walking"; }
};
class Run : public Movement {
public:
void move() { cout << "run"; }
};
class Animal {
public:
virtual void print() = 0;
};
class Human : public Animal {
public:
void print() { cout << "Human"; }
};
class Lion : public Animal {
public:
void print() { cout << "Lion"; }
};
class Model {
Animal* animal;
Movement* movement;
public:
Model(Animal* animal = new Human(), Movement* movement = new Walk()) {
this->animal = animal;
this->movement = movement;
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first = Model(),
second = Model(new Lion(), new Run());
first.print();
cout << endl;
second.print();
return 0;
}
Incidentally, your code can also be made compilable by providing an implementation for Animal::print(). The following code is also compilable, but Animal is not an abstract class because it provides an implementation for Animal::print() rather than suffixing it with = 0:
#include <iostream>
using namespace std;
class Movement {
public:
virtual void move() = 0;
};
class Walk : public Movement {
public:
void move() { cout << "walking"; }
};
class Run : public Movement {
public:
void move() { cout << "run"; }
};
class Animal {
public:
virtual void print() {};
};
class Human : public Animal {
public:
void print() { cout << "Human"; }
};
class Lion : public Animal {
public:
void print() { cout << "Lion"; }
};
class Model {
Animal* animal;
Movement* movement;
public:
Model(Animal* animal = new Human(), Movement* movement = new Walk()) {
this->animal = animal;
this->movement = movement;
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first = Model(),
second = Model(new Lion(), new Run());
first.print();
cout << endl;
second.print();
return 0;
}
Otherwise, conceptually, what you're doing is fine and totally possible in C++: assigning a default value to a base class pointer that's in some function's argument list.
Important: As commenters have correctly pointed out, the pattern you have coded is dangerous: your interface is such that a user can optionally provide an Animal instance. The problem is: if the Model creator does, then it can be reasonably argued that he rightly owns the object. If he does not, then your constructor will create a new Animal instance, but neither does Model take ownership of the object, nor does it provide an interface by which the user can take ownership of the new Animal instance. This therefore creates a memory leak. Equally, the code hazard, is ambiguous ownership of the Animal instance used in the Model constructor.
I have a class derived from base class, and set constructors for each classes, but I keep getting error that I do not have any constructor for base class.
class Dog
{
protected:
string name;
int age;
public:
Dog(string dogsName, int dogsAge)
{
name = dogsName;
age = dogsAge;
}
virtual void Bark()
{
cout << "Woof Woof I am a dog" << endl;
}
class Huey: public Dog
{
public:
Huey()
{
name = "goodboy";
age = 13;
}
void Bark()
{
cout << "woof" << endl;
}
}
Here I get an error on Huey() and it says " no default constructor exists for 'Dog'". But I think I have created a constructor for class Dog. Can you please explain why this code is wrong?
When you specify any constructor of your own, the default constructor is not created anymore. However, you can just add it back.
class Dog
{
protected:
string name;
int age;
public:
Dog() = default;
Dog(string dogsName, int dogsAge)
{
name = dogsName;
age = dogsAge;
}
virtual void Bark()
{
cout << "Woof Woof I am a dog" << endl;
}
};
class Huey: public Dog
{
public:
Huey()
{
name = "goodboy";
age = 13;
}
void Bark()
{
cout << "woof" << endl;
}
};
EDIT: It seems like you want to call your custom Dog constructor from Huey. It is done like so
class Dog
{
protected:
string name;
int age;
public:
Dog(string dogsName, int dogsAge)
{
name = dogsName;
age = dogsAge;
}
virtual void Bark()
{
cout << "Woof Woof I am a dog" << endl;
}
};
class Huey: public Dog
{
public:
Huey() : Dog("goodboy", 13) {}
void Bark()
{
cout << "woof" << endl;
}
};
You need to create a constructor with no parameters and no implementation. As below:
public:
Dog() = default;
Two ways:
1) have a default constructor with no params.
2) call the existing constructor you have in Dog from Huey ( this is the right thing in your case since Huey is a Dog after all). Huey is currently calling the default constructor of Dog since this isn’t defined and explicitly called.
I have just learnt about abstract class but I don't understand much. Is it possible to run abstract class functions and the inherited functions all at once?..
For example,
class Animals
{
public:
virtual void Display() = 0;
};
class Dog : public Animals
{
void Display()
{
cout << "This is Dog!" << endl;
};
class Cat : public Animals
{
void Display()
{
cout << "This is Cat!" << endl;
}
};
and I have another class called Zoo which will run the abstract function in class Animals
class Zoo : public Animals
{
Animals* animal;
animal->Display();
}
and the output I want is
This is Dog!
This is Cat!
When I run this, it has errors.. Is there any other ways to get this output? Thanks :)
First off, there's a syntax error:
class Animals
{
public:
virtual void Display() = 0;
};
class Dog : public Animals
{
void Display()
{
cout << "This is Dog!" << endl;
}
};
class Cat : public Animals
{
void Display()
{
cout << "This is Cat!" << endl;
}
};
Then if you want to create Dog and Cat instances you call new operators for these classes:
class Zoo : public Animals
{
void Display()
{
Animals* animal1;
animal1 = new Cat();
animal1->Display();
delete animal1;
Animals* animal2;
animal2 = new Dog();
animal2->Display();
delete animal2;
}
}
This should get your desired output.
animal->Display(); results in undefined behaviour because animal is not initialized, so first initialized it as
Cat my_cat;
Animals* animal = &my_cat;
animal->Display();
OR
Animals* animal = new Cat();
animal->Display();
....
delete animal;
Here is your Code, explanation is there in comments.
class Animals {
public:
virtual void Display() = 0;/*its a PVF , in every derived class it should be re-defined */
};
class Dog : public Animals {
void Display() {
cout << "This is Dog!" << endl;
};
};
class Cat : public Animals {
void Display() {
cout << "This is Cat!" << endl;
}
};
class Zoo : public Animals {
public :
void Display() {
#if 1
Dog my_dog;
Animals *animal = &my_dog; /** Display() of Animal class will be invoked bcz Display() is declared as virtual */
animal->Display();
#endif
#if 0
Animals* animal = new Cat(); /** Display() of Cat class eill be invoked */
animal->Display();
delete animal;
#endif
}
};
int main() {
Zoo my_zoo;
my_zoo.Display();
return 0;
}
I hope it helps you.
Is there a way to only call the base class and run the inherited classes too?
I think you want this:
#include <iostream>
#include <memory>
class Animals
{
public:
virtual void Display() = 0;
virtual ~Animals() = default;
};
class Dog : public Animals
{
void Display() override
{
std::cout << "This is Dog!" << std::endl;
}
};
class Cat : public Animals
{
void Display() override
{
std::cout << "This is Cat!" << std::endl;
}
};
class Goat : public Animals
{
void Display() override
{
std::cout << "This is Goat!" << std::endl;
}
};
int main()
{
Animals* animal = new Dog;
animal->Display();
delete animal; // delete at some point to avoid memory leak as Dog is allocated on the heap
Cat cat;
animal = &cat;
animal->Display(); // no delete needed, as Cat is allocated on the stack and will cleared when goes out of scope
std::unique_ptr<Animals> animal2 = std::make_unique<Goat>();
animal2->Display(); // no delete needed, Goat is allocated on the heap but will be cleared when goes out of scope
return 0;
}
https://ideone.com/yoVt4G
Threw std::unique_ptr in the mix for variety
I was just revising the basic concepts of OOP and I ran across this. The program works but I can not understand why it works. I have a base class Vehicle and child class Car and Grandchild class TwoDoorCar. The code is given below:
class Vehicle {
private:
int wheels;
string make;
protected:
int protect;
public:
virtual ~Vehicle(){}
Vehicle(){
cout << "empty Vehicle constructor" << endl;
this->wheels = 0;
this->make = "";
this->protect = 0;
}
Vehicle(int wheel,string m){
cout << "parametrized Vehicle constructor" << endl;
this->wheels = wheel;
this->make = m;
this->protect = 0;
}
void ctest() const{ // read only function
cout << "ctest() called" << endl;
}
virtual void Drive() = 0;
const string& getMake() const {
return make;
}
void setMake(const string& make) {
this->make = make;
}
int getWheels() const {
return wheels;
}
void setWheels(int wheels) {
this->wheels = wheels;
}
};
class Car : virtual public Vehicle {
private:
int carNumber;
public:
virtual ~Car(){}
Car():Vehicle(){
cout << "empty car constructor" << endl;
carNumber = 0;
}
Car(int wheels, string make, int Number) : Vehicle(wheels,make){
cout << "Car's constructor called" << endl;
this->carNumber = Number;
}
Car(int wh, string m): Vehicle(wh, m){
this->carNumber = 0;
}
virtual void Drive(){
cout << "Car driven " << endl;
}
virtual void Drive(string p){
cout << "Over loaded function of Drive with string argument : " << p << endl;
}
void testProtect(){
cout << "Car::Protected member " << this->protect << endl;
}
};
class TwoDoorCar : public Car{
public:
virtual ~TwoDoorCar(){}
TwoDoorCar():Car(){
cout << "Empty two door car constructor" << endl;
}
TwoDoorCar(int wheels, string make, int reg) : Car(wheels,make,reg){
}
};
The pure virtual function Drive() is defined in the child class but not in the grandchild class. I tried using virtual in the child class, yet the program works with no function implementation of the Drive() function in the grandchild class.
I run with the following code
TwoDoorCar tdc1;
Vehicle * v3 = &tdc1;
v3->Drive();
The output of the program is
empty Vehicle constructor
empty car constructor
Empty two door car constructor
Car driven
Can anyone explain why there is no error here even though pure virtual and virtual are used in base and child class respectively?
Only pure virtual functions are required to be defined. virtual functions can be derived by inherited classes and does not require to be re-defined in inherited class.
I'm running into an error "C2084 - function 'void Pet::display(void)' already has a body". Error occurs on Dog.cpp file. Slightly confused about the issue. Any help would be appreciated.
Pet.h
#ifndef _PET_H_
#define _PET_H_
#include <string>
using namespace std;
enum Type { dog = 0, cat };
class Pet {
private:
string name, breed; // private local variables
Type type;
public:
Pet(string pet_name, string pet_breed, Type pet_type); // constructor
// accessor methods
string getName();
string getBreed();
Type getType();
virtual void display() {};
};
#endif // _PET_H_
Dog.h
#ifndef _DOG_H_
#define _DOG_H_
#include "Pet.h"
#include <string>
using namespace std;
class Dog : public Pet {
public:
Dog(string pet_name, string pet_breed, Type pet_type) : Pet(pet_name, pet_breed, pet_type) {
} // constructor
virtual void display() = 0;
};
#endif
Dog.cpp
#include "Dog.h"
#include "Pet.h"
#include <iostream>
void Pet::display() {
cout << "Name: " << name << endl;
cout << "Breed: " << breed << endl;
cout << "Type: Dog" << endl;
}
It seems that you wanted to define Dog::display and have forgotten to rename Pet to Dog:
void Dog::display() {
cout << "Name: " << name << endl;
cout << "Breed: " << breed << endl;
cout << "Type: Dog" << endl;
}
Also remove " = 0" from:
virtual void display() = 0;
in "Dog.h".
In "Pet.h" file having " = 0" after function prototype is ok, it means that you shouldn't instantiate the Pet class directly (Abstract class).
In Pet.h you already have a body defined for display(), which does nothing.
In Pet.h:
class Pet {
/* other class members */
virtual void display() {}; // Here is your virtual function with an empty body.
};
In Dog.h:
class Dog : public Pet {
/* other class members */
virtual void display() = 0; // This pure virtual function which is inheriting from Pet which is not purely virtual.
};
Swap the two around.
Make Pet's virtual void display() = 0, i.e. a pure virtual function.
Make Pet's virtual void display(), i.e. a virtual function which you are already implementing in Dog.cpp.
Solution:
In Pet.h:
class Pet {
/* other class members */
virtual void display() = 0; // Make this a pure virtual function. It does not have an implementation.
};
In Dog.h:
class Dog : public Pet {
/* other class members */
virtual void display(); // This virtual function is implemented in Dog.cpp.
};
You are declaring the method display pure virtual in the class Dog which is derived from another class Pet. But the Pet class already has a concrete method called display. That' why you get this error.
Declare display as pure virtual in the Pet class and then give a concrete implementation in its child class Dog.