This is kind of a specific question that I had not been able to find a solution to for quite a while. I have this code:
#include <iostream>
using namespace std;
class Mammal
{
public:
Mammal() {cout << "Mammal Constructor\n";}
virtual ~Mammal() {cout << "Mammal Destructor\n";}
virtual void Run() {cout << "Mammal Ran One Space\n";}
protected:
int mammalDistance;
};
class Horse : public Mammal
{
public:
Horse() {cout << "Horse Constructor\n";}
~Horse() {cout << "Horse Destructor\n";}
void Run() {cout << "Horse Ran One Space\n";}
void Run(int distance) {horseDistance = distance;
cout << "Horse Ran " << horseDistance << " Spaces\n";}
protected:
int horseDistance;
};
int main()
{
Mammal *pHorse = new Horse;
pHorse->Run(5);
delete pHorse;
return 0;
}
Now this code works if I take the void Run(int horseDistance) and move it up into Mammal but I wanted to know if there was a way to keep it in horse without it remaining hidden.
Edit: I mean it compiles and works as intended if I take the function that accepts input and move it up into Mammal instead of having it within the Horse class like it is currently.
Yes I would like it if it could change the value of horseDistance when it is being passed in.
Edit: O I get what your saying. I edited the code.
You have two options. One is to keep track of the fact that your pointer is a horse:
int main()
{
Horse *pHorse = new Horse;
pHorse->Run(5);
delete pHorse;
return 0;
}
The other is to declare a virtual function in Mammal:
virtual void Run(int mammalDistance) = 0;
I'd pick option #1 if horses were the only things running specific distances, option #2 otherwise.
Mammal *pHorse = new Horse;
pHorse->Run(5);
Doesn't work because there is no member function in Mammal with the signature void Run(int). More precise: the function void Run(int) given in the Horse class is not an override for the function void Run() in Mammal, because of the different signatures.
You should consider adding void Run(int) to the Mammal interface, if it is a function more subclasses will implement.
Now you know that pHorse is a Horse, but for the compiler, it is different.
The only way to do it is to check with dynamic cast if pHorse is a horse and then cast it to a Horse* and cast the method Run(5).
Horse* pHorse2=dynamic_cast<Horse*>(pHorse);
if(pHorse2!=NULL){
pHorse2->Run(5);
}else{
pHorse->Run();
}
I think you're looking for polymorphism here. All your derived Mammals simply have to implement getDistance() and setDistance() and also can implement getAnimal() to provide a name. I think there's still some room for improvement on the design, but you'll be getting the hang of polymorphism this way. Something like this perhaps:
#include <iostream>
using namespace std;
class Mammal
{
public:
Mammal() {cout << "Mammal Constructor\n";}
virtual ~Mammal() {cout << "Mammal Destructor\n";}
virtual void Run() {cout << getAnimal() << " Ran " << getDistance() << " Space\n";}
virtual void Run(int p_distance)
{setDistance(p_distance);
cout << getAnimal() << " Ran " << getDistance() << " Spaces\n";}
protected:
virtual void setDistance(int p_distance) {mammalDistance = p_distance;}
virtual int getDistance() {return mammalDistance;}
virtual string getAnimal() {return "Mammal";}
int mammalDistance;
};
class Horse : public Mammal
{
public:
Horse() {cout << "Horse Constructor\n";}
~Horse() {cout << "Horse Destructor\n";}
protected:
int horseDistance;
virtual string getAnimal() {return "Horse";}
};
int main()
{
Mammal *pHorse = new Horse;
pHorse->Run(5);
delete pHorse;
return 0;
}
Related
I am trying to overload a virtual function, like this:
#include<iostream>
#include<string>
using std::cout;
using std::endl;
using std::string;
class Base{
public:
virtual void show(int x){
cout << "Showing int as Base: " << x << endl;
}
};
class Derived : public Base{
public:
using Base::show;
virtual void show(string s){
cout << "Showing string as Derived: " << s << endl;
}
};
int main(){
Derived x;
Base& ref = x;
ref.show(3);
ref.show(string("hi")/*in case the compiler refuses to implicitly convert const char* to std::string*/);
}
However, GCC complains error: cannot convert 'std::string' {aka 'std::__cxx11::basic_string<char>'} to 'int', and says note: initializing argument 1 of 'virtual void Base::show(int)'
It seems like gcc just ignored the Derived's overload of show.
I suspect that overloading together with polymorphism is just a BIT too much to handle for the compiler, since that would require storing the type information in the vtable as well, which MAY be not possible.
But then, what should I do to mimic this behaviour?
This worked:
#include<iostream>
#include<string>
#include<any>
using std::cout;
using std::endl;
using std::string;
using std::any;
using std::any_cast;
class Base{
public:
virtual void show(int x){
cout << "Showing int as Base: " << x << endl;
}
virtual void show(any x) = 0;
};
class Derived : public Base{
public:
using Base::show;
virtual void show(any s) override{
if(s.type() != typeid(std::string)){
if(s.type() != typeid(int)){
throw "SOME_ERROR_INDICATING_INVALID_FUNCTION_CALL";
}
Base::show(any_cast<int>(s));
return;
}
cout << "Showing string as Derived: " << any_cast<string>(s) << endl;
}
};
int main(){
Derived x;
Base& ref = x;
ref.show(3);
ref.show(string("hi")/*invokes show(any) override */);
}
but it seems really stupid. Is there any other workaround?
EDIT: adding virtual void show(string x)=0; to base is NOT desireable. This is just a MRE, and in the real program I have lots of derived classes, and I don't want to add a pure virtual function in Base for each of those customizations.
The problem is that you're calling show through a reference to a base object while passing a std::string as an argument but the base class doesn't have any such method so this call can't succeed.
To solve this you can add a declaration for virtual void show(string s) =0; inside the base class.
class Base{
public:
virtual void show(int x){
cout << "Showing int as Base: " << x << endl;
}
//added this declaration for making it pure virtual
virtual void show(string s)=0;
};
I'm using multiple inheritance in C++ and extending base methods by calling their base explicitly. Assume the following hierarchy:
Creature
/ \
Swimmer Flier
\ /
Duck
Which corresponds to
class Creature
{
public:
virtual void print()
{
std::cout << "I'm a creature" << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
void print()
{
Creature::print();
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
void print()
{
Creature::print();
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer
{
public:
void print()
{
Flier::print();
Swimmer::print();
std::cout << "I'm a duck" << std::endl;
}
};
Now this presents a problem - calling the duck's print method calls its respective base methods, all of which in turn call the Creature::print() method, so it ends up being called twice-
I'm a creature
I can fly
I'm a creature
I can swim
I'm a duck
I would like to find a way to make sure the base method is called only once. Something similar to the way virtual inheritance works (calling the base constructor on the first call, then only assigning a pointer to it on successive calls from other derived classes).
Is there some built-in way to do this or do we need to resort to implementing one ourselves?
If so, how would you approach this?
The question isn't specific to printing. I wondered if there's a mechanism for extending base methods and functionality while keeping the call order and avoiding the diamond problem.
I understand now that the most prominent solution would be to add helper methods, but I just wondered if there's a "cleaner" way.
Most likely this is a XY problem. But ... just don't call it twice.
#include <iostream>
class Creature
{
public:
virtual void identify()
{
std::cout << "I'm a creature" << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
virtual void identify() override
{
Creature::identify();
tell_ability();
std::cout << "I'm a swimmer\n";
}
virtual void tell_ability()
{
std::cout << "I can swim\n";
}
};
class Flier : public virtual Creature
{
public:
virtual void identify() override
{
Creature::identify();
tell_ability();
std::cout << "I'm a flier\n";
}
virtual void tell_ability()
{
std::cout << "I can fly\n";
}
};
class Duck : public Flier, public Swimmer
{
public:
virtual void tell_ability() override
{
Flier::tell_ability();
Swimmer::tell_ability();
}
virtual void identify() override
{
Creature::identify();
tell_ability();
std::cout << "I'm a duck\n";
}
};
int main()
{
Creature c;
c.identify();
std::cout << "------------------\n";
Swimmer s;
s.identify();
std::cout << "------------------\n";
Flier f;
f.identify();
std::cout << "------------------\n";
Duck d;
d.identify();
std::cout << "------------------\n";
}
Output:
I'm a creature
------------------
I'm a creature
I can swim
I'm a swimmer
------------------
I'm a creature
I can fly
I'm a flier
------------------
I'm a creature
I can fly
I can swim
I'm a duck
------------------
We can let the base class keep track of the attributes:
#include <iostream>
#include <string>
#include <vector>
using namespace std::string_literals;
class Creature
{
public:
std::string const attribute{"I'm a creature"s};
std::vector<std::string> attributes{attribute};
virtual void print()
{
for (auto& i : attributes)
std::cout << i << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
Swimmer() { attributes.push_back(attribute); }
std::string const attribute{"I can swim"s};
};
class Flier : public virtual Creature
{
public:
Flier() { attributes.push_back(attribute); }
std::string const attribute{"I can fly"s};
};
class Duck : public Flier, public Swimmer
{
public:
Duck() { attributes.push_back(attribute); }
std::string const attribute{"I'm a duck"s};
};
int main()
{
Duck d;
d.print();
}
Likewise, if it is not just printing we're after, but rather the function calls, then we could let the base class keep track of the functions:
#include <iostream>
#include <functional>
#include <vector>
class Creature
{
public:
std::vector<std::function<void()>> print_functions{[this] {Creature::print_this(); }};
virtual void print_this()
{
std::cout << "I'm a creature" << std::endl;
}
void print()
{
for (auto& f : print_functions)
f();
}
};
class Swimmer : public virtual Creature
{
public:
Swimmer() { print_functions.push_back([this] {Swimmer::print_this(); }); }
void print_this()
{
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
Flier() { print_functions.push_back([this] {Flier::print_this(); }); }
void print_this()
{
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer
{
public:
Duck() { print_functions.push_back([this] {Duck::print_this(); }); }
void print_this()
{
std::cout << "I'm a duck" << std::endl;
}
};
int main()
{
Duck d;
d.print();
}
An easy way is to create a bunch of helper classes that mimick the inheritance structure of your main hierarchy and do all the printing in their constructors.
struct CreaturePrinter {
CreaturePrinter() {
std::cout << "I'm a creature\n";
}
};
struct FlierPrinter: virtual CreaturePrinter ...
struct SwimmerPrinter: virtual CreaturePrinter ...
struct DuckPrinter: FlierPrinter, SwimmerPrinter ...
Then each print method in the main hierarchy just creates the corresponding helper class. No manual chaining.
For maintainability you can make each printer class nested in its corresponding main class.
Naturally in most real world cases you want to pass a reference to the main object as an argument to the constructor of its helper.
Your explicit calls to the print methods form the crux of the issue.
One way round this would be to drop the print calls, and replace them with say
void queue(std::set<std::string>& data)
and you accumulate the print messages into the set. Then it doesn't matter those functions in the hierarchy get called more than once.
You then implement the printing of the set in a single method in Creature.
If you want to preserve the order of printing, then you'd need to replace the set with another container that respects the order of insertion and rejects duplicates.
If you want that middle class method, do not call the base class method. The easiest and simplest way is to extract extra methods, and then reimplementing Print is easy.
class Creature
{
public:
virtual void print()
{
std::cout << "I'm a creature" << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
void print()
{
Creature::print();
detailPrint();
}
void detailPrint()
{
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
void print()
{
Creature::print();
detailPrint();
}
void detailPrint()
{
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer
{
public:
void print()
{
Creature::Print();
Flier::detailPrint();
Swimmer::detailPrint();
detailPrint();
}
void detailPrint()
{
std::cout << "I'm a duck" << std::endl;
}
};
Without details what is your actual problem is, it hard to come up with a better solution.
Use:
template<typename Base, typename Derived>
bool is_dominant_descendant(Derived * x) {
return std::abs(
std::distance(
static_cast<char*>(static_cast<void*>(x)),
static_cast<char*>(static_cast<void*>(dynamic_cast<Base*>(x)))
)
) <= sizeof(Derived);
};
class Creature
{
public:
virtual void print()
{
std::cout << "I'm a creature" << std::endl;
}
};
class Walker : public virtual Creature
{
public:
void print()
{
if (is_dominant_descendant<Creature>(this))
Creature::print();
std::cout << "I can walk" << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
void print()
{
if (is_dominant_descendant<Creature>(this))
Creature::print();
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
void print()
{
if (is_dominant_descendant<Creature>(this))
Creature::print();
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer, public Walker
{
public:
void print()
{
Walker::print();
Swimmer::print();
Flier::print();
std::cout << "I'm a duck" << std::endl;
}
};
And with Visual Studio 2015 the output is:
I'm a creature
I can walk
I can swim
I can fly
I'm a duck
But is_dominant_descendant does not have a portable definition. I wish it were a standard concept.
You are asking for something like inheritance on a function level that automatically calls the inherited function and just adds more code. Also you want it to be done in a virtual way just like class inheritance. Pseudo syntax:
class Swimmer : public virtual Creature
{
public:
// Virtually inherit from Creature::print and extend it by another line of code
void print() : virtual Creature::print()
{
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
// Virtually inherit from Creature::print and extend it by another line of code
void print() : virtual Creature::print()
{
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer
{
public:
// Inherit from both prints. As they were created using "virtual function inheritance",
// this will "mix" them just like in virtual class inheritance
void print() : Flier::print(), Swimmer::print()
{
std::cout << "I'm a duck" << std::endl;
}
};
So the answer to your question
Is there some built-in way to do this?
is no. Something like this does not exist in C++. Also, I'm not aware of any other language that has something like this. But it is an interesting idea...
Imagine if I have class hierachy like this (Inheritance Hierarchy A):
Vehicle
MotorVehicle
Automobile
Motorcycle
WaterCraft
Sailboat
Canoe
If the Vehicle class contains functions named get_retail_price() and get_description(), and the get_description() function is overridden by every subclass in the hierarchy, without a virtual function in the base class, which get_description() function is executed by the following code?
void display_vehicle(const Vehicle& v)
{
std::cout << "Description: " << v.get_description() << ā\nā
<< "Retail price: " << v.get_retail_price() << "\n\n";
}
int main()
{
Motorcycle motorcycle("Harley-Davidson FXDR 114", 21349.0);
display_vehicle(motorcycle);
return 0;
}
I think it is the one in the Vehicle class because every subclass is redefining the get_descritption() function. But it the Vehicle class that calls it. Am I right to assume this?
And last question, what would happen if display_vehicle(const Vechicle& v) had a return type of any class? Something like Automobile display_vehicle(const Vehicle& v). Will it still call get_description() in the Vehicle class?
For member functions that are not virtual, it's the function of the known type that is invoked.
Here, the only known type is Vehicle:
void display_vehicle(const Vehicle& v)
{
std::cout << "Description: " << v.get_description() << ā\nā
<< "Retail price: " << v.get_retail_price() << "\n\n";
}
Note by the way that in such a case, you don't override the funcions. But you define a new function which hides the function of the base class.
If the function would be virtual, it would be the function of the object's real type that would be called.
Here a small snippet to show the different cases:
class Vehicle {
public:
virtual void show() { cout<<"I'm a vehicle"<<endl; } // virtual
void print() { cout <<"I'm a vehicle"<<endl; } // not virtual
void invokeshow() { show(); } // not virtual but invoking virtual
void invokespecificshow() { Vehicle::show(); } // not virtual invoking specific
~Vehicle() {} //at least one virtual ? then virtual destructor
};
class Motorcycle: public Vehicle {
public:
void show() override { cout<<"I'm a motorcycle"<<endl; }
void print() { cout <<"I'm a motorcycle"<<endl; }
};
void test(Vehicle &v) {
v.show();
v.print();
v.invokeshow();
v.invokespecificshow();
}
Online demo
I'm trying to solve an inheritance problem, where a derived class Snake inherits from LivingThing -> Animal -> Reptile, however, when I don't add virtual void crawl() to class LivingThing, the compiler says error: no member named 'crawl' in 'LivingThing'. Now I don't want to have to implement a virtual void in LivingThing which is specific for Snakes.
#include <iostream>
class LivingThing
{
public:
void breathe()
{
std::cout << "I'm breathing as a living thing." << std::endl;
}
virtual void crawl() {} //dont' want this
};
class Animal : virtual public LivingThing
{
public:
void breathe()
{
std::cout << "I'm breathing as an animal." << std::endl;
}
};
class Reptile : virtual public LivingThing
{
public:
void crawl()
{
std::cout << "I'm crawling as a reptile." << std::endl;
}
void breathe()
{
std::cout << "I'm breathing as a reptile." << std::endl;
}
};
class Snake : public Animal, public Reptile
{
public:
void breathe()
{
std::cout << "I'm breathing as a snake." << std::endl;
}
void crawl()
{
std::cout << "I'm crawling as a snake." << std::endl;
}
};
int main()
{
LivingThing *snake = new Snake();
snake->breathe();
snake->crawl();
system("pause");
return 0;
}
snake->crawl(); tries to access crawl through a LivingThing*, without a v-table reference, LivingThing* cannot call Snake::crawl.
In your current example you could just change the LivingThing pointer to be a Snake pointer.
In a more complex situation:
If you know that the pointer you're calling crawl on points to an object that is infact a Snake then you can static_cast the pointer.
if(Snake* snake = static_cast<Snake*>(livingThing))
snake->crawl();
If you have no guarantee that the living thing is actually a Snake and you have rtti available then you can use dynamic_cast.
if(Snake* snake = dynamic_cast<Snake*>(livingThing))
snake->crawl();
When you upcast object to it's base type, you can only use methods which are declared in this base class. So if you don't want to declare crawl method in your base type, you've to downcast your object before using this method:
LivingThing *creature = new Snake();
creature->breathe();
if(Snake* snake = dynamic_cast<Snake*>(creature)) snake->crawl();
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.