I am having a weird problem, which I'm sure has an easy fix. I have a super class let's call it "Bird". Bird has a virtual function called chirp, which returns me 0. I also have a subclass lets call it...SomeOtherBird. SomeOtherBird is a subclass of Bird. The chirp() function for my subclass is supposed to return me 1.
So far:
Bird.Chirp() should return 0
SomeOtherBird.Chirp() should return 1
Some other bird is a subclass of bird.
Now assuming I pass in Bird into a seperate constructor, let's call it nest.
So: nest(Bird& x)
if I pass a SomeOtherBird in, and I call Chirp, it calls the virtual function of the main super-class and not of the subclass, so for example:
SomeOtherBird x;
Nest(x);
and then if I do x.chirp, the main method is called, not the one of the subclass.
How do I get the function in the sub-class to be called, and not the virtual main function?
Thanks
I worked for me.
ideone.com/RRfau
You really ought to include some example code with questions like this so we can help you.
#include <iostream>
#include <typeinfo>
class Bird
{
public:
virtual ~Bird() {}
virtual int chirp() { return 0; }
};
class SomeOtherBird : public Bird
{
public:
virtual int chirp() { return 1; }
};
void nest( Bird& x )
{
std::cout << typeid(x).name() << " says " << x.chirp() << '\n';
}
int main()
{
SomeOtherBird s;
nest( s );
Bird b;
nest( b );
}
Works fine as shown below. Perhaps you might not have made the base method virtual. Or there is something else wrong in the code, since the code was not posted, it is impossible to tell.
#include <iostream>
using namespace std;
class Bird
{
public:
Bird() {}
~Bird() {}
virtual int Chrip() { cout << "Bird version" << endl; return 0; }
};
class SomeOtherBird:public Bird
{
public:
SomeOtherBird() {}
~SomeOtherBird() {}
virtual int Chrip() { cout << "SomeOtherBird version" << endl; return 1; }
};
int nest(Bird &b)
{
b.Chrip();
}
int main()
{
SomeOtherBird s;
Bird &b = s;
int retcode = nest(b);
cout << "retcode " << retcode << endl;
}
Output:
rhdevblade1-~/cpp: ./virt
SomeOtherBird version
retcode 1
Without seeing your code it's impossible to answer you for sure. However, this sounds like you did not write "virtual Bird()" in your base class, only in the derived class. That doesn't work.
class Bird {
virtual int Bird();
};
class MoreBird : public Bird {
int Bird();
};
The virtual keyword is not required in the deriving class (although it is not good practice not to put it there even if 99.9% of the programmers are lazy and don't do it.)
Related
I have some code I'm trying to get to work, I'm open to other suggestions on how to do this. Basically, I have some base class that I want a bunch of subclasses to inherit. I then have a function that needs to call the subclass version of this method.
#include <iostream>
using namespace std;
//my base class
class BaseClass {
public:
void myMethod(){
std::cout << "Base class?" << std::endl;
}
};
/my subclass
class SubClass1: public BaseClass{
public:
void myMethod(){
std::cout << "Subclass?" << std::endl;
}
};
//method that I want to call SubClass.myMethod(). I cannot declare this as
//SubClass1 because there will be multiple of these.
void call_method(BaseClass object){
return object.myMethod();
}
int main()
{
BaseClass bc;
SubClass1 sb1;
//works how I expect it to
sb1.myMethod();
//I want this to also print "Subclass?"
//but it prints "Base class?".
call_method(sb1);
return 0;
}
Thanks for your help
You need to declare the member function in the base class as virtual. For example
virtual void myMethod() const {
std::cout << "Base class?" << std::endl;
}
And in the derived class to override it
void myMethod() const override {
std::cout << "Subclass?" << std::endl;
}
And the function call_method must have a parameter that represents a reference to base class object
void call_method( const BaseClass &object){
object.myMethod();
}
If I have a class that's inheriting from another, is it possible to replace the inherited class in the child? I've got a demo of what I'm trying to do below, but I'm not sure the syntax.
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
m_a = a;
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {};
reset(int b)
{
singleNum::this = *singleNum(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
No
You cannot exchange or reset the base class. If it had a reset method of it's own, you could call this, but you cannot call the constructor again.
If you want to do this, you should favor composition over inheritance. You can then create a completely new instance of the inner composition class and replace your existing instance.
Your current demo isn't hard to implement, but you'll need to modify the parent class:
#include <iostream>
class singleNum
{
public:
int m_a;
singleNum(int a)
{
std::cout << "SETUP" << std::endl;
reset(a);
}
~singleNum()
{
std::cout << "CLOSEDOWN" << std::endl;
}
virtual void reset(int b)
{
m_a = b;
}
};
class inheritor : public singleNum
{
public:
inheritor(int a) : singleNum(a) {}
void reset(int b) override
{
singleNum::reset(b);
}
};
int main()
{
inheritor z(5);
std::cout << z.m_a << std::endl;
z.reset(5);
return 0;
}
But this is the closest you will get to "replacing the base class". If your case is different than the demo presented and you need to call the base class constructor on an already constructed derived object then no, this is not doable.
I am facing the following problem with my code:
#include <iostream>
using namespace std;
class Base {
public:
virtual void sayHello()=0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
};
void sayHello(Impl1 *i) {
cout << "Impl1 says: ";
i->sayHello();
}
void sayHello(Impl2 *i) {
cout << "Impl2 says: ";
i->sayHello();
}
int main()
{
Impl1 *i1 = new Impl1();
Base *b = i1;
sayHello(b);
return 0;
}
And here the compiler complains about the sayHello(b); line in the
code.
"call of overloaded 'sayHello(Base*&)' is ambiguous"
Is there a way to solve this problem?
EDIT:
I basically want to pass my object to a function that does some calculations based on the type of the object. My object intentionally lacks of information in order to make the needed calculations. So Impl1 and Impl2 just contain some basic data, without the knowledge of more data needed to do the calculations.
Overload resolution is performed at compile time. It means for sayHello(b);, the compiler only know that the type of b is Base*, it won't and can't know that b is pointing to a Impl1 object actually. Then results in ambiguous call; converting Base* to Impl1* or Impl2* is equivalent rank for the call.
PS: might be OT, but for you code sample, a function taking a Base* would work fine; dynamic dispach will take effect.
class Base {
public:
virtual void sayHello()=0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
};
void sayHello(Base *i) {
cout << "Some derived class of Base says: ";
i->sayHello();
}
int main()
{
Impl1 i1;
Impl2 i2;
Base *b = &i1;
sayHello(b); // "Hi from Impl1"
b = &i2;
sayHello(b); // "Hi from Impl2"
return 0;
}
If you need to know the dynamic type at run-time, you can use dynamic_cast. e.g.
Base *b = /* something */;
Impl1 * pi1 = dynamic_cast<Impl1*>(b);
if (pi1 != nullptr) sayHello(pi1);
Since overloads are resolved at compile time, you have to supply the compiler with the exact type in order for the overload resolution to succeed.
In order to dispatch on the type, add a virtual member function to the Base, and use it to choose the overload:
class Base {
public:
virtual void sayHello()=0;
virtual void callSayHello() = 0;
};
class Impl1 : public Base {
public:
void sayHello() { cout << "Hi from Impl1" << endl; }
void callSayHello() {sayHello(this); }
};
class Impl2 : public Base {
public:
void sayHello() { cout << "Hi from Impl2" << endl; }
void callSayHello() {sayHello(this); }
};
void sayHello(Impl1 *i) {
cout << "Impl1 says: ";
i->sayHello();
}
void sayHello(Impl2 *i) {
cout << "Impl2 says: ";
i->sayHello();
}
...
b->callSayHello();
Note that implementations of callSayHello are identical, but you cannot place them into Base class, because the type of this would be different.
Note: the idea for this implementation is borrowed from C++ implementation of the Visitor Pattern.
Get rid of the two free-standing functions and call b->sayHello(); directly:
Impl1 *i1 = new Impl1();
Base *b = i1;
b->sayHello();
Or use an ugly workaround with dynamic_cast:
Impl1 *i1 = new Impl1();
Base *b = i1;
sayHello(dynamic_cast<Impl1*>(b));
The need to resort to dynamic_cast often suggests an error in the class design. This may very well be the case here. Chances are that you should never have introduced a supposedly object-oriented base class in the first place.
Note also that you do not call delete at the end. If you do, you will need a virtual destructor in Base.
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);
}
This is part 2 to a problem I previously asked: Is it possible to have polymorphic member overloading in C++?
Using the Wiki example I created this example.
http://en.wikipedia.org/wiki/Double_dispatch
My problem is that the compiled code never looks up the vtable, and always uses the base instead of the inherited class. Here is my code:
#include <iostream>
class xEntity;
class xVehicle;
class xMapObject
{
public:
virtual void Bump(xMapObject&) { std::cout << "MapObject Bump MapObject\n"; };
virtual void Bump(xEntity&) { std::cout << "MapObject Bump Entity\n"; };
virtual void Bump(xVehicle&) { std::cout << "MapObject Bump Vehicle\n"; };
};
class xEntity : public xMapObject
{
public:
virtual void Bump(xMapObject&) { std::cout << "Entity Bump MapObject\n"; };
virtual void Bump(xEntity&) { std::cout << "Entity Bump Entity\n"; };
virtual void Bump(xVehicle&) { std::cout << "Entity Bump Vehicle\n"; };
};
class xVehicle : public xEntity
{
public:
virtual void Bump(xMapObject&) { std::cout << "Vehicle Bump MapObject\n"; };
virtual void Bump(xEntity&) { std::cout << "Vehicle Bump Entity\n"; };
virtual void Bump(xVehicle&) { std::cout << "Vehicle Bump Vehicle\n"; };
};
int main(int argv, char **argc)
{
xEntity Entity;
xVehicle Vechile;
xMapObject &EntityRef = Entity;
xMapObject &VehicleRef = Vechile;
VehicleRef.Bump(EntityRef);
return 0;
}
However, the output is always:
Vehicle Bump MapObject
Any help on this mystery is greatly appreciated.
You only did single dispatch, not double dispatch. The idea is that in xVehicle, taking an xMapObject&, you would call ref.bump(*this); which is double dispatch.
It is using the vtable; that's why it's calling xVechicle::Bump()! The vtable isn't used on arguments, that doesn't make sense (in C++, at least).
The typical solution is to have e.g. Bump(xMapObject& obj) call obj.Bump(*this);.
Is a bad design the xEntity::Bump(xVehicle&) because you are using as parameter in a base class a derived class.
and at least that your contract change, you don't need redefine base Bump methods.
the problem is that you are creating the xMapRef vars, that convert your derived class to a base class.
if you want that appropriated method is called, just call with the derived class object