I am trying a basic thing with two classes and a free functions. First I have two classes :
struct BASE{
BASE(int a = 0):a_(a){};
virtual ~BASE(){};
virtual void foo(){std::cout << "BASE " << std::endl;}
int a_;
};
struct DERIVED: public BASE{
DERIVED():BASE(){};
void foo(){std::cout << "DERIVED " << std::endl;}
};
then I fill up a std::vector (or boost::ptr_vector)
std::vector<BASE* > vec;
vec.push_back( new BASE(2));
vec.push_back( new DERIVED);
If I call my function foo, no pb the virtual stuff works well,
but if I create two free functions :
void foo(BASE* a, DERIVED* b){
std::cout << " mix base/derived " << std::endl;
}
void foo(BASE* a, BASE* b){
std::cout << " full base " << std::endl;
}
if I do
foo(vec[0], vec[1]); //failed
I will get the message
full base
Well it is logical because I have vector of BASE*, but does it exist anyway
to get the good call to my free function ? I need the inheritance so I can not really separate the 2 classes because I must fill up this container
Moreover at the end my vector will be fill up randomly, so I can not know by advance how cast properly.
The simplest (and quickest) way to get workaround is to introduce one more virtual function to unique identify derived classes (using int, enum values or typeid). So later you may call it and realize what exact derived class (or maybe base) you've got behind the BASE*, and do dynamic_cast to that type.
You gave no details about what problem you are trying to solve... just make sure that you've done a complete reaseach for existed solutions if you want to implement a Double Dispatch (or some kind of)...
But usually, if you need dynamic_cast it means that smth wrong with you design (OOP model of domain)...
Just as you don't know in advance what your vec[i] is, so doesn't the compiler. Function overload resolution is a compile time process, while polymorphism - run time.
Thus it calls the void foo(BASE* a, BASE* b) version.
In other words, what you want to do is impossible, unless you use dynamic_cast to try to cast to every possible derived class. It will return 0 if the object is of wrong type.
However, many people will argue that use of dynamic_cast is indication of bad design. And it's expensive as well.
You need dynamic dispatching for that, something like this:
void foo(BASE *a, BASE *b) {
if (DERIVED *bb = dynamic_cast<DERIVED*>(b)) {
foo(a, bb);
} else {
std::cout << " full base " << std::endl;
}
}
If you don't want to use a dynamic_cast, you could add a virtual function to BASE which would return some form of class identifier (e.g. an enum), override this in each derived class and then fork the call based on the return value of this function (along with static_cast).
Related
I have an issue where the method I'm trying to call isn't called and some other method is called instead. It is in a very weird and big design but I managed to do a example out of it. The example is still big the it's the smaller I've been able to do.
#include <iostream>
#include <vector>
class IObserver
{
};
class IAObserver : public IObserver
{
public:
virtual void someSpecificMethod(int i) = 0;
};
class ISomeOtherObject
{
public:
virtual void someMethodFromThatObject() = 0;
};
class SomeOtherObject : public ISomeOtherObject
{
public:
virtual void someMethodFromThatObject()
{
std::cout << "Some implementation from that object" << std::endl;
}
};
class AObserverImpl : public IAObserver, public SomeOtherObject
{
public:
virtual void someSpecificMethod(int i)
{
std::cout << "Some implementation " << i << std::endl;
}
virtual void someMethodFromThatObject()
{
std::cout << "Better implementation from our object" << std::endl;
}
};
class Base
{
public:
virtual void addObserver(IObserver* observer) = 0;
};
class A : public Base
{
public:
virtual void addObserver(IObserver* observer)
{
m_observers.push_back((IAObserver*)observer);
}
void notifyObservers()
{
std::vector<IAObserver*>::iterator it;
for(it = m_observers.begin(); it != m_observers.end(); it++)
{
(*it)->someSpecificMethod(5);
}
}
private:
std::vector<IAObserver*> m_observers;
};
int main()
{
A* a = new A();
SomeOtherObject* observer = new AObserverImpl();
a->addObserver((IObserver*)observer);
a->notifyObservers(); //output: Better implementation from our object
}
Here's the Ideone http://ideone.com/yAT6M7
So as you can see, it is supposed to call the method someSpecificMethod but it's calling the mehod someMethodFromThatObject. Any clue what's going on ? Is this object slicing ? In CLion debugger, I can't even call my someSpecificMethod method. How can I work around this ?
The problem is that you are using C-style casts, when you should be using a dynamic_cast instead.
C-style casts know nothing of C++ objects, and therefore they do no type checking. In order to cast between base classes in a multiple-inheritance situation, you must use a dynamic_cast to make sure that everything is set up correctly for the new pointer.
If you replace all of the C-style casts in your sample to dynamic_cast, then it should work.
If you want to read more about this, search for C++, v-tables, and multiple inheritance.
At the core of your problem is a cross-cast. You have an inheritance hierarchy that looks like this:
[SomeOtherObject] [IAObserver]
\ /
\ /
[AObserverImpl]
Inside main(), observer has dynamic type AObserverImpl*, but static type SomeOtherObject*. Then you try to retrieve the IAObserver part of the object which also contains this SomeOtherObject. This is called a cross-cast, a cast across the inheritance tree of an object.
But by the time you do the cast, the information that *observer is actually part of an AObserverImpl has been lost from the type system. So the C-style cast, which is strictly static, degrades into a reinterpret_cast (!!). You get an IAObserver* that actually still points to the very same SomeOtherObject, and trying to then use it only leads to nasty bugs at best.
This is the kind of reasons why you should never use a C-style cast on pointers unless you have a good reason and you know it. Had you used a static_cast, it would have failed to compile.
To solve this, you need to somehow get back the lost type information to perform your cast. Two parties still have that information:
The developer:
// Downcast to AObserverImpl, then upcast along the other branch
// The upcast is superfluous, but written here for clarity
a->addObserver(
static_cast<IAObserver*>(
static_cast<AObserverImpl*>(observer)
)
);
And... dynamic_cast:
// dynamic_cast uses RTTI to walk the inheritance graph at runtime.
// It will also do error checking :)
a->addObserver(dynamic_cast<IAObserver*>(observer));
I have this code:
#include <iostream>
class Super{
public:
virtual void showName();
};
class Special1 : public Super {
public:
void showName();
void sayHello();
};
class Special2 : public Super {
public:
void showName();
void sayGoodbye();
};
void Super::showName() {
std::cout << "I'm super!" << std::endl;
}
void Special1::showName() {
std::cout << "I'm special1" << std::endl;
}
void Special1::sayHello() {
std::cout << "Hello" << std::endl;
}
void Special2::showName() {
std::cout << "I'm special2" << std::endl;
}
void Special2::sayGoodbye() {
std::cout << "Goodbye" << std::endl;
}
int main () {
Super *oSpec=new Super;
Special1 *o1=static_cast<Special1 *>(oSpec);
Special2 *o2=static_cast<Special2 *>(oSpec);
oSpec->showName();
o1->showName();
o2->showName();
o1->sayHello();
o2->sayGoodbye();
delete oSpec;
return 0;
}
When I run it, it shows this output:
I'm super!
I'm super!
I'm super!
Hello
Goodbye
But, if I remove the virtual keyword from the declaration of the Super class:
class Super{
public:
/*virtual*/ void showName();
};
The output becomes the correct one:
I'm super!
I'm special1
I'm special2
Hello
Goodbye
Then, my question is, why the presence of the virtual keyword makes the pointers o1 and o2 run the method Super::showName() instead of Special1::showName() or Special2::showName()?
The output is closer to correct with virtual and incorrect with it (unless you really wanted that). The cast doesn't change the type of the objects, just the type of the pointers. They are still of type Super, and so it's Super::showName that should run.
Casting one pointer type to another pointer type doesn't change the type of the thing pointed to. How could it? The whole point of virtual functions is to be able to call methods on 'generic' pointers and get the correct derived class method.
The classic example of why you use virtual functions is for musicians. You might have a function that causes the entire orchestra to play by calling the Play method on every Musician * it gets passed. For a Pianist, that has to call Pianist::Play.
Normally, the compiler figures out which function to call at compile time -- early binding. The only information the compiler is sure to know is the type of the pointer. The virtual keyword causes the binding to occur late, at run time, when the actual type of the class member is known.
By the way, you can still call the base class method, by using a scope override. For example o1->Super::showName();.
In fact, the result you claim is 'correct' is catastrophic. Running Special1::showName() with the this pointer pointing to an object that is not of type Special1 (or something derived from it) is undefined behavior and can easily lead to a crash.
Because your code in main is wrong. The objects all say "I'm super" because for them (in reality, in the background), the most derived type is still super. That's what they were created as.
Your static cast breaks all the rules, to be undefined behavior (anything can happen), because you tell the compiler that o1 is a Special1, when in fact, it is not a type of Special1.
virtual functions are usually useful when you create a bunch of derived objects, and store them in a pointer/container that holds pointers to the base object. Not the other way around. You want to create pointers of type Special1 and Special2 and store them in pointers to super.
Your cast (Special1 *o1=static_cast<Special1 *>(oSpec);) is undefined behavior in both cases, so any output at all is acceptable as far as the language is concerned. You've taken an object of type Super and lied to the compiler, telling it that it's really a derived class. In this case, what happens is that you still get the result of the parent class Super that it really is.
Your code is just undefined.
Trying to reason why it works in a particular way is useless.
Here:
Super *oSpec=new Super;
oSpec points at an object of type Super.
Thus in these statements. The casts have undefined behavior, as the object pointed at by oSpec is neither a Special 1 or a Special 2).
Special1 *o1=static_cast<Special1 *>(oSpec);
Special2 *o2=static_cast<Special2 *>(oSpec);
If you use dynamica_cast<> (like you should when casting up the class hierarchy). You will find the result are NULL.
Special1 *o1=dynamic_cast<Special1 *>(oSpec);
Special2 *o2=dynamic_cast<Special2 *>(oSpec);
std::cout << "O1(" << (void*)o1 << ") O2(" << (void*)o2 << ")\n";
This will show that both pointers are NULL.
Given the following class structure:
class Base
{
virtual void outputMessage() { cout << "Base message!"; }
};
class Derived : public Base
{
virtual void outputMessage() { cout << "Derived message!"; }
}
.. and this code snippet:
Base baseObj;
Derived* convertedObj = (Derived*) &baseObj;
convertedObj->outputMessage();
.. the output will be "Base message!".
Is there any way to cast or manipulate the object to make Derived's version of the outputMessage method to be called polymorphically?
Edit: I will attempt to show the reason why I'm after this:
I am writing migration tools that hook into our main system. For this reason, I need to get access to protected member methods, or customise existing virtual methods. The former I can do by defining a derived class and casting objects to it, to call methods statically. What I can't do is change the behaviour for methods which I do not call statically (ie methods that are called elsewhere in the codebase).
I have also tried creating objects of the derived class directly, but this causes issues in other parts of the system due to the manipulation of the objects passed through the constructor.
No, virtual functions operate on the actual types of the object being pointed to, which in your case is just a simple Base.
Actually, with the down-casting, you're entering undefined-behaviour land here. This can blow off like a bomb with multiple inheritance, where the vtable in the derived class isn't at the same offset as the vtable in the base class.
No Standard-compliant solution
What you're trying to do isn't possible using behaviours guaranteed by the C++ Standard.
If you really MUST do this as a short-term measure to assist your migration, don't depend on it in production, and can adequately verify the behaviour, you could experiment as illustrated below.
Discussion of your attempt
What I'm showing is that you're taking the wrong approach: simply casting a pointer-to-base to a pointer-to-derived doesn't alter the object's vtable pointer.
Deriving a plausible hack
Addressing that, the naive approach is to reconstruct the object in place as a derived object ("placement" new), but this doesn't work either - it will reinitialise the base class members.
What you can possibly do is create a non-derived object that has no data members but the same virtual dispatch table entries (i.e. same virtual functions, same accessibility private/protected/public, same order).
More warnings and caveats
It may work (as it does on my Linux box), but use it at your own risk (I suggest not on production systems).
Further warning: this can only intercept virtual dispatch, and virtual functions can sometimes be dispatched statically when the compiler knows the types at compile time.
~/dev cat hack_vtable.cc
// change vtable of existing object to intercept virtual dispatch...
#include <iostream>
struct B
{
virtual void f() { std::cout << "B::f()\n"; }
std::string s_;
};
struct D : B
{
virtual void f() { std::cout << "D::f()\n"; }
};
struct E
{
virtual void f() { std::cout << "E::f()\n"; }
};
int main()
{
B* p = new B();
p->s_ = "hello";
new (p) D(); // WARNING: reconstructs B members
p->f();
std::cout << '\'' << p->s_ << "'\n"; // no longer "hello"
p->s_ = "world";
new (p) E();
p->f(); // correctly calls E::f()
std::cout << '\'' << p->s_ << "'\n"; // still "world"
}
~/dev try hack_vtable
make: `hack_vtable' is up to date.
D::f()
''
E::f()
'world'
Well, even if you're casting your Base object as a Derived one, internally, it's still a Base object: the vftable of your object (the actual map of functions to RAM pointers) is not updated.
I don't think there is any way to do what you want to do and I don't understand why you'd like to do it.
In this question downcast problem in c++ Robs answer should also be the answer to your problem.
Not at least in legal way. To call Derived class function, you need to have Derived object being referred.
What is the purpose of using the reserved word virtual in front of functions? If I want a child class to override a parent function, I just declare the same function such as void draw(){}.
class Parent {
public:
void say() {
std::cout << "1";
}
};
class Child : public Parent {
public:
void say()
{
std::cout << "2";
}
};
int main()
{
Child* a = new Child();
a->say();
return 0;
}
The output is 2.
So again, why would the reserved word virtual be necessary in the header of say() ?
Thanks a bunch.
If the function were virtual, then you could do this and still get the output "2":
Parent* a = new Child();
a->say();
This works because a virtual function uses the actual type whereas a non-virtual function uses the declared type. Read up on polymorphism for a better discussion of why you'd want to do this.
Try it with:
Parent *a = new Child();
Parent *b = new Parent();
a->say();
b->say();
Without virtual, both with print '1'. Add virtual, and the child will act like a Child, even though it's being referred to via a pointer to a Parent.
This is the classic question of how polymorphism works I think. The main idea is that you want to abstract the specific type for each object. In other words: You want to be able to call the Child instances without knowing it's a child!
Here is an example:
Assuming you have class "Child" and class "Child2" and "Child3" you want to be able to refer to them through their base class (Parent).
Parent* parents[3];
parents[0] = new Child();
parents[1] = new Child2();
parents[2] = new Child3();
for (int i=0; i<3; ++i)
parents[i]->say();
As you can imagine, this is very powerful. It lets you extend the Parent as many times as you want and functions that take a Parent pointer will still work. For this to work as others mention you need to declare the method as virtual.
If you do not use the virtual keyword you are not overriding, but rahter defining an unrelated method in the derived class that will hide the base class method. That is, without the virtual, Base::say and Derived::say are unrelated --besides the name coincidence.
When you use the virtual keyword (required in the base, optional in the derived class), you are telling the compiler that classes that derive from this base will be able to override the method. In that case, Base::say and Derived::say are considered overrides of the same method.
When you use a reference or pointer to a base class to call a virtual method, the compiler will add the appropriate code so that the final overrider is called (the override in the most derived class that defines the method in the hierarchy of the concrete instance in use). Note that if you do not use references/pointer but local variables, the compiler can resolve the call and it does not need to use the virtual dispatch mechanism.
Well I tested it for myself, because there are a lot of things we can think about:
#include <iostream>
using namespace std;
class A
{
public:
virtual void v() { cout << "A virtual" << endl; }
void f() { cout << "A plain" << endl; }
};
class B : public A
{
public:
virtual void v() { cout << "B virtual" << endl; }
void f() { cout << "B plain" << endl; }
};
class C : public B
{
public:
virtual void v() { cout << "C virtual" << endl; }
void f() { cout << "C plain" << endl; }
};
int main()
{
A * a = new C;
a->f();
a->v();
((B*)a)->f();
((B*)a)->v();
}
output:
A plain
C virtual
B plain
C virtual
I think that a good, simple and short answer might look like this (because I think people who can understand more can memorize less thus needing for short and simple explanation):
Virtual methods checks for the DATA of the instance the pointer points to, while classic methods don't thus calling the method correponding to the specified type.
The point of that feature is the following: suppose you have an array of A's. The array can contain B's, C's, (or even derived types.). if you want to sequentially call the same method of all those instances, you would call each one you overloaded.
I find this quite tricky to understand, and obviously any C++ course should explained how this is achieved, because most of the time you are just teached about virtual functions, you use them, but until you understand how the compiler understand them and how the executable will handle the calls, you are in the dark.
The thing about VFtables is that I have never been explained what kind of code it adds, and that's obviously here where C++ requires much more experience than C, and this might be the main reason C++ was labelled as "slow" in its early days: in fact, it's powerful, but just like everything, it's powerful if you know how to use it, or else you just "blow your whole leg off".
When you use the keyword virtual, a virtual function table is created to locate the correct methods in an instance. Then, even if the derived instance is pointed to by a base class pointer, it will still find the correct implementation of the method.
Suppose we have two classes as follows:-
class Fruit {
protected:
int sweetness;
char* colour;
//...
public:
void printSweetness() const {
cout<<"Sweetness : "<<sweetness<<"\n";
return;
}
void printColour() const {
cout<<"Colour : "<<colour<<"\n";
return;
}
virtual void printInfo() const {
printSweetness();
printColour();
return;
}
};
class Apple : public Fruit {
private:
char* genus;
//...
public:
Apple() {
genus = "Malus";
}
void printInfo() const {
Fruit::printInfo();
cout<<"Genus : "<<genus<<"\n";
return;
}
};
And now suppose we have some function like the following...
void f() {
Fruit* fruitList[100];
for(int i = 0; i<100 ; i++) {
fruitList[i]->printInfo();
}
return;
}
In cases like above, we can call the same function and rely on the Dynamic Dispatch Mechanism and the abstraction it provides without knowing what kind of fruits are stored in that array. This simplifies the code to a great deal and increases the readability. And is far far better than using type fields which makes the code ugly!
Whereas in the overridden method, we must know what kind of object we are dealing with or otherwise face the object slicing problem which may lead to unexpected results.
Note - I have written this answer just to explicitly show the benefits.
This is a very important aspect of c++ programming-- almost every interview I've been to, I get asked this question.
What happens if you change your main to:
int main() { Parent* a = new Child(); a->say(); return 0; }
Also, it's worth understanding what a vtable is.
I have the following two classes, one inherits from the other
Class A{
void print(){cout << "A" << endl;}
}
Class B : A{
void print(){cout << "B" << endl;}
}
Class C : A{
void print(){cout << "C" << endl;}
}
Then in another class I have the following:
vector<A> things;
if (..)
things.push_back(C());
else if (..)
things.push_back(B());
things[0].print();
this always prints A
I'd like it to print B or C depending on which thing I've added to the vector
how do I do this?
I've tried abstraction but I'm not entirely sure how to use it in C++ and it hasn't been working for me
As mentioned, you need virtual functions to enable polymorphic behaviour and can't store classes directly by value in the vector.
When you use a std::vector<A>, you are storing by value and thus objects that you add, e.g. via push_back() are copied to an instance of an A, which means you lose the derived part of the objects. This problem is known as object slicing.
As already suggested you can avoid that by storing pointers (or smart pointers) to the base class, so only pointers are copied into the vector:
std::vector<A*> things;
things.push_back(new B());
// ... use things:
things[0]->print();
// clean up later if you don't use smart pointers:
for(std::vector<A*>::iterator it = things.begin(); it != things.end(); ++it)
delete *it;
1) You need to declare print() as virtual in class A.
2) Your vector is incorrect -- you can't store actual class A objects in there; you will need to store pointers to them for the correct behavior (and you will have to clean up after them later) and/or use something like a boost::shared_ptr.
You need to declare the function virtual in your base class, in this case that's class a:
class A{
virtual void print(){cout << "A" << endl;}
}
The other classes will pick this up even if you don't write virtual in those (but you can).
Virtual tells the compiler that the function could be overridden. When you don't use virtual, it's called hiding and works differently, as you've found.