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.
Related
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;
}
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'm making an inventory system, and am trying to use derivatives to create different items, so that I can have default elements in the parent and specialized ones in the children.
So what I've written below, at the moment it prints "I'm a parent" but I am trying to get it to print "I'm a kid", and in the lack of a child definition of stuffToSay print "I'm a parent" Thanks!
using namespace std;
class myParent {
public:
virtual void saySomething() {
cout << stuffToSay;
}
string stuffToSay = "I'm a parent";
private:
};
class myDerivitive : public myParent{
public:
myDerivitive() {};
string stuffToSay = "I'm a kid";
private:
};
int main() {
myParent* people[] = {
new myDerivitive()
};
cout << people[0]->stuffToSay;
system("pause");
}
Thats not how it works. The saySomething in parent doesn't know anything about the string in the derived class and member variables aren't virtual.
You can do it e.g. like this
#include <iostream>
#include <string>
struct myParent {
void saySomething() {
cout << getSomething();
}
virtual std::string getSomething(){ return "I'm a parent"; }
virtual ~myParent(){} // virtual destructor is needed
};
struct myDerived : myParent {
virtual std::string getSomething(){ return "I'm the derived"; }
};
int main() {
myParent* p = new myDerived();
p->saySomething();
delete p; // dont forget to delete !!
}
Something like this is normally done using the constructor of your class, the child class has all the variables of its parent class so to do what you are looking for it can be done like this:
using namespace std;
class myParent {
public:
myParent() {
stuffToSay = "I'm a parent"
}
virtual void saySomething() {
cout << stuffToSay;
}
string stuffToSay;
private:
};
class myDerivitive : public myParent{
public:
myDerivitive() {
stuffToSay = "I'm a kid";
};
private:
};
int main() {
myParent* people = new myDerivitive();
cout << people->stuffToSay();
delete people; // Simplified to a single pointer and remember to delete it
people = NULL;
system("pause");
}
Please take a look at this link for more information on classes:
http://www.cplusplus.com/doc/tutorial/classes/
This link will help with the understanding of inheritance, since your derivative class would have the "stuffToSay" variable since its parent had it:
http://www.cplusplus.com/doc/tutorial/inheritance/
There is no such thing as a virtual or overridden variable in C++; that sort of polymorphism only applies to methods. So you could do this:
struct parent {
virtual void saySomething() {
cout << "I'm a parent!\n";
}
};
struct child: parent {
void saySomething() override {
cout << "I'm a child!\n";
}
};
Or you could solve it with something more like your current structure by adding a layer of indirection:
struct parent {
void saySomething() {
cout << thingToSay() << '\n';
}
private:
virtual string thingToSay() { return "I'm a parent!"; }
};
class child: parent {
virtual string thingToSay() { return "I'm a child!"; }
};
Please help me, i'm pretty new to objective C++ and i do not know how to get to variable inicjatywa correctly.
I do not know what is wrong. It is possible that i do not fully understand virtual and abstract classes so i would be greatfull for explaining my mistake.
I want program to output the value of inicjatywa ( value = 5) from my object Wolf, using the pointer from Organizmy class.
class Organizmy
{
public:
int inicjatywa;
virtual void akcja() = 0;
virtual void kolizja() = 0;
virtual void rysowanie() = 0;
virtual ~Organizmy(){};
};
class Animal: public Organizmy
{
public:
int inicjatywa;
virtual void akcja() = 0;
virtual void kolizja() = 0;
virtual void rysowanie() = 0;
virtual ~Animal(){};
};
class Wolf: public Animal
{
public:
int inicjatywa;
Wolf(){
cout << "Crate Wolf" << endl;
this->inicjatywa = 5;
};
~Wolf(){};
void akcja(){};
void kolizja(){};
void rysowanie(){
cout << "W" << endl;
cout << this->inicjatywa << endl; // here he output 5
};
};
int main()
{
Organizmy *b; // I create new poiter; type Organizmy
b=new Wolf(); // He is now pointing new object Wolf
b->rysowanie(); // here he outputs correct value of the new elemnt
cout<<b->inicjatywa<< endl; //but here the code outputs -8421....
//and it should be 5 not -8421....
}
A few things. First name your functions sensible things, those names are gibberish and mean nothing to anyone on here.
Second, you're error is quite simple. The "Wolf" and "Animal" class do not need to re-declare "inicjatywa," so long as they declare their inheritance of "Organizmy" to be public (as they have) the 'outside world' will see all the public elements of "Organizmy." The code will look like this:
class Organizmy
{
public:
int inicjatywa;
virtual void akcja() = 0;
virtual void kolizja() = 0;
virtual void rysowanie() = 0;
virtual ~Organizmy(){};
};
class Animal: public Organizmy
{
public:
virtual void akcja() = 0;
virtual void kolizja() = 0;
virtual void rysowanie() = 0;
virtual ~Animal(){};
};
class Wolf: public Animal
{
public:
Wolf(){
cout << "Crate Wolf" << endl;
inicjatywa = 5;
};
~Wolf(){};
void akcja(){};
void kolizja(){};
void rysowanie(){
cout << "W" << endl;
cout << inicjatywa << endl; // here he output 5
};
};
int main()
{
Organizmy *b; // I create new poiter; type Organizmy
b=new Wolf(); // He is now pointing new object Wolf
b->rysowanie(); // here he outputs correct value of the new elemnt
cout<<b->inicjatywa<< endl; //but here the code outputs -8421....
//and it should be 5 not -8421....
}
In c++ pass to a function/method a derived class, in the place of a base class and still have information about the derived class?.
Ex: Say that I have a base class: "geometry" and some other class: "shape" form where I derive "rectangle" and "circle".
double area::geometry( shape& object, int i )
{
if i = 1:
rectangle thisObject = object;
double side1 = thisObject.getheight();
double side2 = thisObject.getwidth();
if i = 2:
circle thisObject = object;
double side1 = thisObject.radius * thisObject.radius;
double side2 = 3.14;
return side1 * side2;
}
The problem is that you have to suppose that the "return side1 * side2", is a very complicated code that I don't want to repeat. So I prefer to set up the problem depending on the type of input to the function, than to overload it.
The idea is very similar to this one: Is it possible to pass derived classes by reference to a function taking base class as a parameter.
Thanks!
Edit: Tried to make the code clearer.
The usual approach would be to use polymorphism:
void func(const base& ob)
{
ob.doSomethingPolymorphic();
}
where doSomethingPolymorphic() is a virtual member function of base.
If func needs to know what type ob is when you pass it in, "you are doing it wrong". The WHOLE POINT of polymorphism is that all objects appear to be the same from an outside observer, but internally do different things. The typical example is animals:
#include <iostream>
using namespace std;
class Animal
{
public:
virtual void Say() = 0;
};
class Dog : public Animal
{
public:
void Say() { cout << "Woof Woof" << endl; }
};
class Pig : public Animal
{
public:
void Say() { cout << "All animals are equal, but pigs are "
"more equal than other animals" << endl; }
};
class Cat : public Animal
{
public:
void Say() { cout << "Meow, Meow" << endl; };
};
void AnimalTalk(Animal *a[], int size)
{
for(int i = 0; i < size; i++)
{
a[i]->Say();
}
}
int main()
{
Cat c;
Pig p;
Dog d;
Animal* list[3] = { &p, &c, &d };
AnimalTalk(list, 3);
}