Classes, Inheritence and virtual functions - c++

class Musician {
public: virtual void play() { std::cout << "Play an instrument"; }
};
class Guitarist : public Musician {
public: void play() { std::cout << "Play a guitar"<<endl; }
};
int main(){
Musician armstrong;
Guitarist steve;
Musician* m = &armstrong;
m->play();
m = &steve; //type of (m)=Musician type of (*m) = Guitarist???
}
Why is the type of (*m) = Guitarist? And why if I remove virtual keyword in function of Musician class then type of (*m) = Musician?
class Musician {
public: void play() { std::cout << "Play an instrument"; } //this makes type of(*m) = Musician
};
If I add armstrong = static_cast<Musician>(steve); at the end it donot give error but cause no change (of addr and type) to armstrong. What is the meaning of that line?
Whereas steve = static_cast<Guitarist>(armstrong); gives error :
error: no matching function for call to 'Guitarist::Guitarist(Musician&)'
27 | steve=static_cast<Guitarist>(armstrong);
| ^

Have tried to do this before while I was learning here's I had come with a solution you can replace A with Musician and B with Guitarist.
#include <iostream>
class A {
public:
void Same(){
std::cout << "From A" << std::endl;
}
virtual A& operator= (const A& a) {
assign(a);
return *this;
}
protected:
void assign(const A& a) {
}
};
class B : public A {
public:
void Same(){
std::cout << "From B" << std::endl;
}
virtual B& operator= (const A& a) {
if (const B* b = dynamic_cast<const B*>(&a))
assign(*b);
return *this;
}
protected:
void assign(const B& b) {
A::assign(b);
}
};
int main(){
A a;
B b;
a.Same();
a = b;
a.Same();
return 0;
}

Related

Using the dynamic_cast operator

I'm trying to understand dynamic type casting.
How to properly implement the DrawAnimals and Talk To Animals functions using dynamic_cast?
DrawAnimals draws animals that can be drawn. Such animals implement the Drawable interface.
TalkToAnimals conducts a conversation with animals that can talk, that is, they implement the Speakable interface.
class Speakable {
public:
virtual ~Speakable() = default;
virtual void Speak(ostream& out) const = 0;
};
class Drawable {
public:
virtual ~Drawable() = default;
virtual void Draw(ostream& out) const = 0;
};
class Animal {
public:
virtual ~Animal() = default;
void Eat(string_view food) {
cout << GetType() << " is eating "sv << food << endl;
++energy_;
}
virtual string GetType() const = 0;
private:
int energy_ = 100;
};
class Bug : public Animal, public Drawable {
public:
string GetType() const override {
return "bug"s;
}
void Draw(ostream& out) const override {
out << "(-0_0-)"sv << endl;
}
};
class Cat : public Animal, public Speakable, public Drawable {
public:
void Speak(ostream& out) const override {
out << "Meow-meow"sv << endl;
}
void Draw(ostream& out) const override {
out << "(^w^)"sv << endl;
}
string GetType() const override {
return "cat"s;
}
};
void DrawAnimals(const std::vector<const Animal*>& animals, ostream& out) {
/*if (const Animal* r = dynamic_cast<const Animal*>(&animals)) {
} else if (const Bug* c = dynamic_cast<const Bug*>(&animals)) {
}*/
}
void TalkToAnimals(const std::vector<const Animal*> animals, ostream& out) {
//?
}
void PlayWithAnimals(const std::vector<const Animal*> animals, ostream& out) {
TalkToAnimals(animals, out);
DrawAnimals(animals, out);
}
int main() {
Cat cat;
Bug bug;
vector<const Animal*> animals{&cat, &bug};
PlayWithAnimals(animals, cerr);
}
I am going to explain for DrawAnimals and you can extended to other functions by yourself.
What you did here:
void DrawAnimals(const std::vector<const Animal*>& animals, ostream& out) {
/*if (const Animal* r = dynamic_cast<const Animal*>(&animals)) {
} else if (const Bug* c = dynamic_cast<const Bug*>(&animals)) {
}*/
}
Is plain wrong for several reasons:
animals is a vector
If you intended an individual element, then because &animals[i] (i = [0..animals.size()]) is a pointer to pointer (Animal**)
Because dynamic_cast<const Animal*>(animals[i]) (i = [0..animals.size()]) is the identity.
You need to work with each individual element of the vector:
void DrawAnimals(const std::vector<const Animal*>& animals, ostream& out) {
for (auto animal : animals) {
if (const Drawable* r = dynamic_cast<const Drawable*>(animal)) {
// this animal is Drawable
} else if (const Bug* c = dynamic_cast<const Bug*>(animal)) {
// this animal is a Bug
// only issue here: Bugs are also Drawable
// so this code will never be reached
}
}
}
Question: Why are some animals Drawable and other don't?

Visitor pattern from base class

I am trying to implement the visitor pattern in c++ https://en.wikipedia.org/wiki/Visitor_pattern
How can I use this pattern when dealing with objects as their base class? I want the visitor to be able to parse the class hierarchy. In my specific case, not the example I give, I want to parse an array of objects into a json list where each object has both the parent class members and the specific subclass members. Is the visitor pattern not the correct approach here?
#include <iostream>
#include <vector>
class Animal;
class Dog;
class Cat;
class Visitor {
public:
virtual void visit(Animal *a) = 0;
virtual void visit(Dog *d) = 0;
virtual void visit(Cat *c) = 0;
};
struct Animal {
void accept(Visitor &v) { v.visit(this); }
int a;
protected:
Animal(int an) : a(an) {}
};
struct Dog : Animal {
Dog(int dn, int an) : Animal(an), d(dn) {}
void accept(Visitor &v) { v.visit(this); }
int d;
};
struct Cat : Animal {
Cat(int cn, int an) : Animal(an), c(cn) {}
void accept(Visitor &v) { v.visit(this); }
int c;
};
struct ConcreteVisitor : Visitor {
void visit(Animal *a) {
std::cout << "Animal<" << a->a << ">";
}
void visit(Dog *d) {
std::cout << "Dog<" << d->d << ", ";
visit((Animal *)d);
std::cout << ">" << std::endl;
}
void visit(Cat *c) {
std::cout << "Cat<" << c->c << ", ";
visit((Animal *)c);
std::cout << ">" << std::endl;
}
};
int main() {
std::vector<Animal *> animals;
animals.push_back(new Dog(4, 5));
animals.push_back(new Cat(6, 7));
ConcreteVisitor v;
for (Animal *a : animals) {
a->accept(v);
}
}
This prints Animal<5> Animal<7>
You should make accept virtual as well.

Polymorphism does not work with pointers, operator<< overload, inheritance, C++

I have a problem with my code. I have two classes, A and B, and B inherits A. I also have operators << overloaded in both classes.
Everything works, I have no compiler errors, but it seems something is wrong. As far as I understand polymorphism, when I use pointers to base class while creating child class with new, calling a method should match the child class, not the base class.
For the code below,
#include <iostream>
using namespace std;
class A
{
protected:
int a;
public:
A(int aa) : a(aa) {};
virtual void show(ostream& o) const
{
o << "a = " << a << "\n";
}
};
ostream& operator << (ostream& os, const A &o)
{
o.show(os);
return os;
}
class B : public A
{
private:
int b;
public:
B(int bb, int aa) : A(aa), b(bb){}
int getb() const {return b;}
};
ostream & operator << ( ostream & os, const B & o)
{
os << static_cast <const A &>(o);
os << "\n";
os << "b = " << o.getb() << "\n";
return os;
}
int main()
{
A *o1 = new B(2,3);
cout << *o1;
cout << "---------------------\n";
B *o2 = new B(2,3);
cout << *o2;
return 0;
}
In main:
A *o1 = new B(2,3);
cout << *o1;
Shows a = 3, instead of showing a = 3 b = 2 (the call should match the child class, not the base class). The thing is, I need to implement the << and >> operators in every child class, but I think they do not behave as they should.
The output of the program:
Even the modified code with re-implmented show method shows wrong results, it does not show a at all this time:
#include <iostream>
using namespace std;
class A
{
protected:
int a;
public:
A(int aa) : a(aa) {};
virtual void show(ostream& o) const
{
o << "a = " << a << "\n";
}
};
ostream& operator << (ostream& os, const A &o)
{
o.show(os);
return os;
}
class B : public A
{
private:
int b;
public:
B(int bb, int aa) : A(aa), b(bb) {}
int getb() const
{
return b;
}
void show(ostream& o) const
{
o << "b = " << b << "\n";
}
};
ostream & operator << ( ostream & os, const B & o)
{
os << static_cast <const A &>(o);
o.show(os);
return os;
}
int main()
{
A *o1 = new B(2,3);
cout << *o1;
cout << "---------------------\n";
B *o2 = new B(2,3);
cout << *o2;
return 0;
}
enter image description here
you have to implement the virtual function show in derived class B:
class B: public A
{
public:
// some code here
virtual void show(ostream& o) const
{
o << "b = " << b << "\n";
}
};
when I use pointers to base class while creating child class with new,
calling a method should match the child class, not the base class
It does when you call a member function ("method" in some other languages), but operator<< is not a member function – it's an overloaded free function.
When choosing an overload, only the types known at compile-time are used.
Since o1 is an A*, *o1 is an A&, and the overload for A& is chosen.
You're doing this a bit "backwards"; you only need one operator<<, for the base class, which calls the virtual show, and then you override show in the derived classes.
Like this:
class A
{
// ...
virtual void show(ostream& o) const
{
o << "a = " << a << "\n";
}
};
ostream& operator << (ostream& os, const A &o)
{
o.show(os);
return os;
}
class B : public A
{
// ...
void show(ostream& o) const override
{
A::show(o); // Do the "A part".
o << "b = " << b << "\n";
}
};
Follow the same pattern for operator>>.

c++ how to call function with subclass, having superclass pointer

I have 3 classes, A, B and C:
class A {
public:
virtual bool sm(B b) = 0;
virtual bool sm(C c) = 0;
};
class B : public A {
bool sm(B b) {
//code
}
bool sm(C c) {
//code
}
};
class C : public A {
bool sm(B b) {
//code
}
bool sm(C c) {
//code
}
};
And vector<A*> objects, that stores B or C objects. (for example they generates randomly)
Can I call somehow
for(int i = 0; i < objects.size(); i++) {
for(int j = i; j < objects.size(); j++) {
objects[i].sm(objects[j]);
}
}
Without dynamic cast or something? Because there can be a bit more of B-C classes
And is it a bag thing, and may be there is a better way to do it?
SOLUTION
As odelande said and I understood, this is the solution for my problem
#include <iostream>
#include <vector>
class B;
class C;
class A {
public:
virtual bool sm(A* a) = 0;
virtual bool sm(B* b) = 0;
virtual bool sm(C* c) = 0;
};
class B : public A {
public:
bool sm(A* a) {
return a->sm(this);
}
bool sm(B* b) {
std::cout << "In B doing B" << std::endl;
return true;
}
bool sm(C* c) {
std::cout << "In B doing C" << std::endl;
return false;
}
};
class C : public A {
public:
bool sm(A* a) {
return a->sm(this);
}
bool sm(B* b) {
std::cout << "In C doing B" << std::endl;
return true;
}
bool sm(C* c) {
std::cout << "In C doing C" << std::endl;
return false;
}
};
int main() {
std::vector<A*> objects;
objects.push_back(new B());
objects.push_back(new C());
objects[0]->sm(objects[0]);
objects[0]->sm(objects[1]);
objects[1]->sm(objects[0]);
objects[1]->sm(objects[1]);
std::cin.get();
return 0;
}
This code outputs
In B doing B
In C doing B
In B doing C
In C doing C
You cannot do it like this. The overloads of the sm() method are statically resolved, i.e. at compile time (besides, sm() should take pointers to B and C). But the compiler only knows that objects[j] is an A*; it cannot resolve the call because there is no overload that takes a A* as input.
What you want is to dispatch the call based on the runtime type of objects[j]. This is what a call to a virtual function does. So, you should only have one sm() method, which should in turn call another virtual method of its argument.
You're searching for the Visitor Pattern, multiple dispatch. The key is that you take a reference in sm(A& a) and call smT(...) on it. (Code is for example purposes only, will need clean-up and consts.)
class A {
protected:
virtual bool smB(B& b) = 0;
virtual bool smC(C& c) = 0;
public:
virtual bool sm(A& a) = 0;
};
class B : public A {
protected:
bool smB(B& b) {
// code,
}
bool smC(C& b) {
// code
}
public:
bool sm(A& a) {
a.smB( *this ); // this is smC(...) in class C
}
};

C++ operator overloading in abstract class

Let's say we have the following scenario:
We have a base abstract class A. Then we have classes B and C which derived from A. We also have class D which is a custom implementation of a std::vector<T> - it contains a private property list of type std::vector<T> and some custom methods to work with it.
Now my problem is as follows: I would like to overload the operator + in class A to be able to do this:
B* b = new B();
C* c = new C();
D mList = b+c; //the property *list* of mList would contain b an c
I have tried everything and can't seem to be able to get it to work and am out of ideas. Is it even possible to override an operator in a base abstract class so that it will apply to derived classes?
EDIT:
Here is what I have tried so far:
File A.h:
#pragma once
#include <string>
#include <iostream>
using namespace std;
class A
{
protected:
double price;
string name;
public:
A() :name(""){};
A(string n, double p){
price = p;
name = n;
};
~A(){};
virtual void calculate(double value) = 0;
virtual void print() const = 0;
};
File B.h:
#pragma once
#include "A.h"
class B : public A
{
private:
public:
B() :A(){};
B(string n, double p) :A(n,p){};
~B();
void calculate(double value)
{
price = price + value;
}
void print() const
{
cout << name << " says: " << " " << price;
}
};
File C.h:
#include "A.h"
class C : public A
{
private:
public:
C() :A(){};
C(string n, double p) : A(n,p){};
~C();
void calculate(double value)
{
price = price * value;
}
void print() const
{
cout << name << " says: " << " " << price;
}
};
File D.H:
#include <vector>
class D
{
private:
vector<A*> list;
public:
D(){}
~D()
{
int len = list.size();
for (int i = 0; i < len; i++)
{
delete list[i];
}
};
void push(A* item)
{
list.push_back(item);
}
A* pop()
{
A* last = list.back();
list.pop_back();
return last;
}
//I have tried overriding it here and in A.h
friend D D::operator+(A* first, A* second)
{
D temp;
temp.push(first);
temp.push(second);
return temp;
}
};
It looks like you're are adding two pointers, so A::operator+() won't even be called. But to answer your question, yes, operator overloading is inheritable. Even from an abstract base class.
class A
{
public:
virtual void test() = 0;
int operator+(const A &a) {return 42;}
};
class B : public A
{
void test() {};
};
class C : public A
{
void test() {};
};
int main()
{
B* b = new B();
C* c = new C();
cout << "result: " << *b + *c << endl;
return 0;
}
Output:
result: 42
When c in C* and d is a D* if you write c+d you're just adding pointers, whatever overloads you defined.
Maybe you could redefine pointer addition for A* with a global operator(A*, A*) (not sure it's possible) but it would be quite dangerous for users since it overrides standard behavior.
The better solution is to define operators on references (const) and not pointers, which in your case is a little less convenient since you'd have to write: list = *c + *d;
Also, since you're using containers of pointers for polymorphism, I strongly recommend using shared_ptr.
Working code below (simplified, but with the ability to add more than 2 elements):
#include <list>
using std::list;
struct A {
list<const A*> operator+(const A& right) { // A + A
list<const A*> r;
r.push_back(this);
r.push_back(&right);
return r;
}
list<const A*> operator+(const list<const A*> & right) { // A + list
list<const A*> r = right;
r.push_front(this);
return r;
}
virtual void print() const = 0;
};
list<const A*> operator+(const list<const A*> & left, const A & right) { // list + A
list<const A*> r = left;
r.push_back(&right);
return r;
}
#include <iostream>
struct B : A {
void print() const { std::cout << "B" << std::endl; }
};
struct C : A {
void print() const { std::cout << "C" << std::endl; }
};
int main() {
B b;
C c;
B* pb = new B;
list<const A*> lst = b + c + *pb;
for(list<const A*>::iterator i = lst.begin(); i != lst.end(); ++i) {
(*i)->print();
}
return 0;
}
Take a look at this code-example:
#include <iostream>
class B;
class A;
class A
{
public:
virtual void overrideProp() = 0;
friend int operator+(const B& b, const A& a);
friend std::ostream& operator<<(std::ostream& os, const A& a)
{
return os << a.prop;
}
protected:
int prop;
};
class B : public A
{
public:
B(){overrideProp();}
void overrideProp(){prop=1;}
};
class C : public A
{
public:
C(){overrideProp();}
void overrideProp(){prop=3;}
};
int operator+(const B& b, const A& a)
{
return b.prop + a.prop;
}
class D
{
public:
void operator=(const int& i){d = i;}
friend std::ostream& operator<<(std::ostream& os, const D& a)
{
return os << a.d;
}
private:
int d;
};
int main()
{
B b;
C c;
D d; d = b+c;
std::cout << "B contains: " << b << " C contains: " << c << " D contains: " << d;
}
The output is B contains: 1 C contains: 3 D contains: 4
Here's an compilable and runnable example (http://codepad.org/cQU2VHMp) I wrote before you clarified the question, maybe it helps. The idea is that the addition overload can either be unary (and D defined as a friend), as here, or defined as a non-member binary operator using public methods. Note that I have to dereference the pointers b and c to make this work, as adding pointers often don't make sense.
#include <iostream>
#include <string>
class D {
public:
void Foo() {
std::cout << "D: " << member_ << std::endl;
}
friend class A;
private:
std::string member_;
};
class A {
public:
virtual void Foo() = 0;
A(const std::string &member) : member_(member) {}
D operator+(const A &rhs) {
D out;
out.member_ = member_ + " " + rhs.member_;
return out; // Uses the default copy constructor of D
}
protected:
std::string member_;
};
class B : public A {
public:
B(const std::string &member) : A(member) {}
void Foo() {
std::cout << "B: " << member_ << std::endl;
}
};
class C : public A {
public:
C(const std::string &member) : A(member) {}
void Foo() {
std::cout << "C: " << member_ << std::endl;
}
};
int main() {
B *b = new B("hello");
C *c = new C("world");
b->Foo();
c->Foo();
D d = (*b) + (*c);
d.Foo();
delete b;
delete c;
return 0;
}
The output of this program is:
B: hello
C: world
D: hello world