Overriding vs Virtual - c++

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.

Related

What are the use cases for a base class pointer pointing to a derived class object

I'm a new to OOP and trying to learn C++ and I came cross polymorphism and using the virtual keyword.
I just don't understand why we might need to do that.
I've checked this site for similar questions but none of them attempts to answer that why?
The main goal is: Separation of concerns.
Let's take an example from my day job. I work on a codebase that does networking. The vast majority of the codebase depends on a class that looks like:
class Transport
{
public:
virtual bool SendMessage(int clientId, string message);
};
Imagine I've got hundred files, and tens of thousand of lines of code, using this class.
Now, my colleague in the low-level team wants to allow our code to use both UDP and TCP for communications. They can simply implement:
class UdpTransport:public Transport
{
public:
bool SendMessage(int clientId, string message) override { /* their code */};
};
class TcpTransport:public Transport
{
public:
bool SendMessage(int clientId, string message) override { /* their code */};
};
This allows me to keep the whole of my code unchanged (using only Transport* or Transport&) and not have to worry about what a UdpTransport or TcpTransport is. It allows one part of the code to work without knowing what another part of the code is doing.
Most introductions of polymorphism start with something like this:
Base* b = new Derived(); // ouch :/
This is very unfortunate in my humble opinion, because it creates the misunderstanding that polymorphism implies manual memory managment via new. The topics are somewhat related. Though my example of polymorphism would start like this:
#include <iostream>
struct base {
virtual void say_hello() { std::cout << "hello base\n"; }
};
struct derived : base {
void say_hello() override { std::cout << "hello derived\n";}
};
void foo(base& b) {
b.say_hello();
}
int main()
{
base b;
derived d;
foo(b);
foo(d);
}
say_hello must be declared virtual to allow derived to override the method. If say_hello was not virtual then derived::say_hello would not override it.
If you remove virtual and override above you can see what happens when the method in the derived class does not override the method in the base class. The call b.say_hello() would then call base::say_hello() no matter if a base or derived is passed to foo because only for virtual methods the method to be called considers the dynamic type of the object.
What are the use cases for a base class pointer pointing to a derived class object
Same as the reference above. foo(base&) can take an object of any type that derives from base and then call its say_hello method. If this wasnt possible you would have to write a foo(derived), foo(derived2), foo(derived3) to call their say_hello method. In a nutshell, polymorphism means to treat different types the same. foo does not need to know what the dynamic type of its paramter is. It only needs to know that it inherites from base.
Many Design Patterns (GOF book) rely on virtual functions. The idea is that you have you work with an object of which you only know it's interface and when you call a function, what is done is based on the object that implements the interface.
One of the design patterns is Command where you have a container in which you can add command implementations and the handler of the container calls the "execute" function without having to worry about what the command actually is. The command implementation contains already the data it needs to run.
A common alternative for virtual functions is a switch case that needs to know all the implementations as an enum so the caller knows what to call exactly or an own implementation of a function-table.
Of course, if you don't see how such thing can improve your program, then it's best not to try and force it in.
Consider the following class architecture and function:
#include <iostream>
#include <string>
class Base
{
public:
std::string hello() const
{
return "Hello Base!";
}
};
class Derived : public Base
{
public:
std::string hello() const
{
return "Hello Derived!";
}
};
void outputHello(const Base& b)
{
std::cout << b.hello() << '\n';
}
We have:
A base class with a hello() method that returns "Hello Base!";
A derived class with a hello() method that returns "Hello Derived!";
A outputHello(const Base&) function that takes a reference to a Base object as its argument and prints out the result of a call to its hello() method.
Now, what do you think the following program will output?
int main()
{
Base b;
outputHello(b);
Derived d;
// Allowed as a reference/pointer to Base can
// reference/point to a Derived object
outputHello(d);
}
You probably guessed the following if you come from Java or a similar object-oriented language:
Hello Base!
Hello Derived!
But it instead it outputs Hello Base! twice. Why? It's actually quite simple. When the compiler gets to the outputHello function body it sees std:cout << b.hello() << '\n'. It thinks: Well, b is of type Base, so I'm gonna issue a call to Base::hello(). And it does exactly that, regardless of the type of the object we actually pass as argument to outputHello.
To solve this problem and get the output we expected, we need RTTI (Runtime Type Information), whose name speaks for itself. This is achieved by marking Base::hello() as virtual:
class Base
{
public:
virtual std::string hello() const
{
return "Hello Base!";
}
};
It is also good practice to mark Derived::hello() as override, though it is not necessary — override functions are automatically virtual.
class Derived : public Base
{
public:
std::string hello() const override
{
return "Hello Derived!";
}
};
We then get our expected output.

Object not calling the good method after casting it's pointer to a base

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));

What is the opposite of c++ `override` / `final` specifier?

In c++11 the override specifier protects from not overriding an intended virtual base function (because the signatures do not match).
The final specifier protects from unintentionally overriding a function in a derived class.
=> Is there a specifier (something like maybe first or no_override) that protects from overriding an unknown base function?
I'd like to get a compiler error when a virtual function was added to a base class with the same signature as an already existing virtual function in a derived class.
EDIT 4: To keep this question simple and answers relevant, here is again the
original pseudo-code
abstract class B : A has private: virtual void fooHasBeenDone() = 0;
class C : B implements private: virtual void fooHasBeenDone() override { react(); }
Now class A gets a new private: virtual void fooHasBeenDone();
But the new A::foo could be something different than the original B::foo.
and a specific example
abstract class B : A has virtual void showPath() = 0; meaing a PainterPath
class C : B implements virtual void showPath() override { mPath.setVisible(); }
Now class A gets a new virtual void showPath(); meaning a file path
Now when A calls showPath(), B shows the painterPath instead of some file path.
Of course this is wrong, and I should then rename B::showPath() to B::showPainterPath() and implement B::showPath() override as well. I'd just like to get informed by the compiler.
Here is a compiling real-world example:
#include <iostream>
#define A_WITH_SHOWPATH
class A
{
#ifdef A_WITH_SHOWPATH
public:
void setPath(std::string const &filepath) {
std::cout << "File path set to '" << filepath << "'. Display it:\n";
showPath();
}
// to be called from outside, supposed to display file path
virtual void showPath() {
std::cout << "Displaying not implemented.\n";
}
#else
// has no showPath() function
#endif
};
class B : public A
{
public:
virtual void showPath() = 0; // to be called from outside
};
class C1 : public B {
public:
virtual void showPath() override {
std::cout << "C1 showing painter path as graphic\n";
}
};
class C2 : public B {
public:
virtual void showPath() override {
std::cout << "C2 showing painter path as widget\n";
}
};
int main() {
B* b1 = new C1();
B* b2 = new C2();
std::cout << "Should say 'C1 showing painter path as graphic':\n";
b1->showPath();
std::cout << "---------------------------\n";
std::cout << "Should say 'C2 showing painter path as widget':\n";
b2->showPath();
std::cout << "---------------------------\n";
#ifdef A_WITH_SHOWPATH
std::cout << "Should give compiler warning\n or say \"File path set to 'Test'. Display it:\"\n and \"Displaying not implemented.\",\n but not \"C1 showing painter path as graphic\":\n";
b1->setPath("Test");
std::cout << "# Calling setPath(\"Test\") on a B pointer now also displays the\n# PainterPath, which is not the intended behavior.\n";
std::cout << "# The setPath() function in B should be marked to never override\n# any function from the base class.\n";
std::cout << "---------------------------\n";
#endif
return 0;
}
Run it and look at the text output.
For reference, an older example with a specific use-case (PainterPath instance):
https://ideone.com/6q0cPD (link may be expired)
The facility of specifiers like first or no_override is not there as such. Probably because it may create confusion. However, it can trivially be achieved by changing the approach.
One should add any new method in the base class with final specifier. This will help to get the compiler error for any matching signatures. Because, it will make the subsequent derived class method signatures automatically as "first" of their kind. Later the final keyword can be removed, as it was intended just for "first hand verification".
Putting & removing final keyword after the newly added base method is analogically similar to compiling binary with debug (g++ -g) option, which helps you to fix bug. In production that debug option is removed for optimization.
From your example:
class A {}; // no method, no worry
class B {
public: virtual void showPath() = 0; // ok
};
...
Now accidentally you are adding similar method in A, that results in error:
class A {
public: virtual void showPath() final; // same signature by chance
// remove the `final` specifier once the signature is negotiated
};
class B {
public: virtual void showPath() = 0; // ERROR
};
So the signatures between new A::showPath() & existing B::showPath() have to be negotiated & then carry on by removing final specifier.
This answer is community wiki because it combines all other answers. Please upvote the specific answer that was helpful to you as well as this one.
No, there is no specifier like first or no_override. (answer)
You should use the override specifier as often as possible.
Qt has a macro Q_DECL_OVERRIDE that expands to override, if available.
If not available, at least mark each overriding function with a comment.
If you do that, there are compiler flags that warn about a missing override:
"Clang now has -Winconsistent-missing-override, and newer GCCs have -Wsuggest-override."
I don't know of a VS2012 flag for this. Feel free to edit.
You can mimic the desired behavior by adding a 'secret' that the base class cannot know. (answer)
This is helpful in very specific use cases, but generally breaks the concept of virtuality (see comments to the other answers).
If you don't own the base class and have a conflict (e.g. compiler warning), you will need to rename your virtual function in all derived classes.
If you own the base class, you can temporarily add a final to any new virtual function. (answer)
After the code compiles without errors, you know that no function of that name and signature exists in any derived class, and you can remove the final again.
... I think I'll start marking first virtual functions as DECL_FIRST. Maybe in the future there will be a compiler-independent way of checking this.
No there is not.
Adding a virtual function to a base class that has the same signature as a virtual function in a child class cannot break any existing functionality unless adding that virtual function turns the base class into a polymorphic type. So in the norm, it's benign, and a purest would argue, adding language features to guard against this would be rather pointless.
(Of course you could mark your new function final just to check that a child class function isn't going to clobber it.)
Your only option is to resort to code analysis tools.
(Note that VS2012 does not implement, or even claim to implement, the C++11 standard, although it does have some of it.)
C++ doesn't seem to provide such means out of the box. But you can mimic it like follows:
template<class Base>
class Derived : public Base
{
private:
struct DontOverride {};
public:
// This function will never override a function from Base
void foo(DontOverride dummy = DontOverride())
{
}
};
If you intend to introduce a new virtual function, then do it like below:
template<class Base>
class Derived : public Base
{
protected:
struct NewVirtualFunction {};
public:
// This function will never override a function from Base
// but can be overriden by subclasses of Derived
virtual void foo(NewVirtualFunction dummy = NewVirtualFunction())
{
}
};

Abstract Classes and Losing Information

I have a question about creating classes from an abstract class and how data gets cut.
Let's say we have an abstract class called Animal, and classes called Cat and Dog that implement said class. Both these classes implement a method from Animal called update(); however, in their update methods they access private methods and/or variables that are exclusive to themselves and not the Animal class. I understand that if we declare the classes in this manner...
Animal* dog = new Dog();
Animal* cat = new Cat();
We're only able to access methods or variables that only the Animal class specifically has; however, what if I called the update() method on each class instead, and this update method calls on the exclusive members in Cat and Dog. Would that be legal, or would this data be truncated because I created them as Animal?
The language does not force you to use only the polymorphic access to method 'update()'.
Example:
class Animal {
public:
virtual void update() { std::cout << "Animal::update() " << std::endl; }
virtual ~Animal(){}
};
class Cat : public Animal {
public:
virtual ~Cat(){}
virtual void update() { std::cout << "Cat::update() " << std::endl; }
};
class Dog : public Animal {
public:
virtual ~Dog(){}
virtual void update() { std::cout << "Dog::update() " << std::endl; }
};
int t395(void)
{
Animal* dog = new Dog();
Animal* cat = new Cat();
dog->update();
cat->update();
dog->Animal::update();
return (0);
}
// OUTPUT:
// Dog::update()
// Cat::update()
// Animal::update()
...We're only able to access methods or variables that only the Animal
class specifically has;
I agree ... dog is an Animal, and does not have a method Bark, and thus would not be able to invoke dog->bark(). But, you could add a method "virtual void talk()" to all three, and perhaps a virtual void Dog::talk() would simply invoke its local Dog::bark() method, and Cat::talk() would simply invoke it's local Cat::meow() method.
however, what if I called the update() method on each class instead,
and this update method calls on the exclusive
members in Cat and Dog. Would that be legal, or would this data be
truncated because I created them as Animal?
Legal - yes. Data is NOT truncated (in either Animal or Dog or Cat)
a) The polymorphic dog is-a Animal, and has all methods and data attributes of Animal.
b) It also has all the methods and attributes of Dog.
Implementation is compiler specific, but one typical impl. is that the two structures (there are some complication needing compiler attention) are simply concatenated in memory. Which is first doesn't matter - its an implementation issue.
Both cat and dog instances have access to their own data and method attributes, regardless of if these method are not mapped into the polymorphic table.
Also, both cat and dog instances have access to those parts of the parent Animal instance that are public or protected (but not private).
Not sure I fully understand your question, but your update() describes a virtual function call.
I suspect you are having problems understanding how inheritance and polymorphism is implemented, I know I did. Consider the following:
class base
{
private:
int mylocalInt; //inaccessible to anyone but the base.
protected:
int sharedInt = 5;//accessible by base, and any subtype.
public:
base()
{
cout<<"creating base object"<<endl;
}
virtual ~base()
{
cout<<"Now destroying base object"<<endl;
}
void virtual callMe()//will be overridden, only called if you directly instantiate a base object.
{
cout<<"I am a base"<<endl;
}
};
class subtypeA : public base
{
private:
int Aint;
public:
subtypeA()
{
cout<<"creating subtype"<<endl;
}
~subtypeA()
{
cout<<"destroying subtype"<<endl;
}
void callMe()
{
cout<<"I am a subtypeA"<<endl;
}
int getAint()//this is a local, IE static function, a base ptr cannot access it.
{
return Aint;
}
int getSharedInt()//notice how sharedInt, located in the base object, is still accessible from within the subtype.
{
return sharedInt;
}
};
int main(int argc, char* argv[] )
{
base* ptr = new subtypeA;
ptr->callMe();//works fine, will check which subtype, if any, ptr points to, and call the appropriate callMe(). This is because
//callMe() is virtual in base.
//ptr->sharedInt//illegal, main is not part of base or a subtype of base.
subtypeA* Aptr = (subtypeA*)ptr;//since all pointers are the same size, they can be cast to one another, is dangerous however
cout<<Aptr->getSharedInt()<<endl;//works, getSharedInt is NOT virtual, but a normal static member of subtypeA, so in order to use it, the pointer
//needs to be of type subtypeA. the sharedInt however is protected, so subtypeA can access it due to the fact that it is related to it's owner, base.
}
Now take that, and play around with it, add a subtypeB, then add subtype to that subtype, IE subtypeAA and BB for instance.
Notice that each individual class is still it's own object, distinct from any of the objects it is related to. So if a variable is private, it can't be directly accessed from the outside, just as with normal objects.
Again: There is nothing truly special about polymorphism, all it is is a nice abstraction hiding the "ugly" type-checking and so forth going on to facilitate virtual calls.
I completely forgot about your other question. No, you never have to worry about truncation in this case. In fact I asked more or less the same question some time ago, take a look: C++ subtype degeneration when placed in a container
dasblinkenlight explains it brilliantly.

free function and inheritance

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).