C++ override virtual method with abstract class as a parameter - c++

I have a following abstract class
class A {
public:
virtual void foo(A* a) = 0;
}
and several classes inheriting from this class. e.g
class B : public A {
public:
void foo(A* a); // implementation in a separete file
}
However, I only want class B to accept itself as an argument in foo
void foo(B* b);
Is it possible to do this in C++?
I've considered a template but the syntax allows too much flexibility. It is possible to write class B: public A<B>, but I want a compiler error with class B: public A<C>.
-- Edit --
It seems like my use of abstract class is not justified. Let me clarify my situation.
I am utilizing a polymorphic behavior of A in a separate function. In addition to that, I want to define a function that takes in an argument of the same type such as the one above. I am trying to write a function that defines the distance between two objects of a derived class. Distance is only defined between objects from the same class (b1 and b2, or c1 and c2, but not b1 and c2). I also would like to access this distance function in a general way as possible.
-- Edit 2--
Cássio showed why it is not possible to perform compiler based checking. zar's solution adds slightly more structure to the code with runtime error checking.

I understand your question is more about the syntax. What you have is right, just pass an object of type B. The definition will still say A but it will be happy to take the derived class. You don't need any special definition for this.
class A {
public:
virtual void foo(A* a) = 0;
};
class B : public A {
public:
void foo(A* a)
{
if (dynamic_cast<B*> (a) == NULL)
std::cout << "wrong type, expecting type B\r\n";
}
};
class C : public A {
public:
void foo(A* a)
{
if (dynamic_cast<C*> (a) == NULL)
std::cout << "wrong type, expecting type C\r\n";
}
};
int main()
{
B * b1 = new B;
B * b2 = new B;
C * c1 = new C;
C * c2 = new C;
b2->foo(c1); // bad
c1->foo(b1); // bad
b2->foo(b1); // good
delete b1;
delete b2;
delete c1;
delete c2;
}
see also dynamic_cast.

That's not what virtual is for.
virtual is there to enable polymorphic behavior. Basically, to enable this:
struct A {virtual void foo()=0;};
// Two different "behaviors" for the same "A"
struct B {void foo() override{}};
struct C {void foo() override{}};
// forgive the leak, this is just to prove a point.
A* b = new B();
A* c = new C();
b->foo(); // Will call B::foo, even though this is a pointer to "A"
c->foo(); // Will call C::foo, even though this is a pointer to "A"
The way you're trying to use it, you lose this benefit, and you just get the performance hit of virtual functions for nothing. The fact that instantiating a class that doesn't implement some pure virtual function is an error is merely to prevent ill-formed programs.
If you want to make sure B implements some interface, simply use that interface somewhere. If B does not implement it, you will get the compiler error you're looking for:
class B {};
template<typename T> void call_foo(T* v1, T* v2) {
v1->foo(&v2);
}
B b1;
B b2;
b1.foo(&b2); // error
call_foo(&b1, &b2); // error
Then, to get rid of the error, you can just implement the function. No virtual needed:
class B {
void foo(B*) {/*do something*/}
};
B b1;
B b2;
b1.foo(&b2); // ok
call_foo(&b1, &b2); // ok
But, why can't I use a virtual function for this?
Imagine the following scenario:
struct A {virtual void foo(A*)=0;};
// Imagine if the language allowed this:
struct B {void foo(B*) override{}};
struct C {void foo(C*) override{}};
// (...)
// I create a vector of objects, and insert three of them in this vector.
std::vector<A*> objects;
// Note that foo is well-defined only for the first two.
objects.push_back(new B();)
objects.push_back(new B();)
objects.push_back(new C();)
// Then I shuffle the vector
std::shuffle(objects.begin(), objects.end());
// At least one of these three lines should give a compiler error.
// Which one(s)?
objects[0]->foo(objects[1]);
objects[0]->foo(objects[2]);
objects[1]->foo(objects[2]);
But I need the function to be virtual, and I need type safety!
Virtual functions are a runtime mechanism. You will have to check the type at runtime. zar's answer already covers this up nicely, so I won't get into the details. To sum it up: simply dynamic_cast into the type you want, and if the cast returns nullptr, you have the wrong type. You can then throw an exception or print some diagnostic message.

Related

Upcast to abstract base class

I try to have an abstract base class act like an interface and instantiate a derived class based on user input. I tried to implement it like this
class A
{
public:
virtual void print() = 0;
};
class B : A
{
public:
void print() override { cout << "foo"; }
};
class C : A
{
public:
void print() override { cout << "bar"; }
};
int main()
{
bool q = getUserInput();
A a = q ? B() : C();
a.print();
}
But that does not work. I’m coming from c# and that would be valid c# so I’m looking for an equivalent way of implement it in c++. Could someone please give me a hint? Thanks!
There are two problems with the code in its current state.
By default in C++, a class that inherits from a class or struct will be private inheritance. E.g. when you say class B : A, it's the same as writing class B : private A -- which in C++ restricts the visibility of this relationship only to B and A.
This is important because it means that you simply cannot upcast to an A from outside the context of these classes.
You are trying to upcast an object rather than a pointer or reference to an object. This fundamentally cannot work with abstract classes and will yield a compile-error even if the code was well formed.
If the base class weren't abstract, then this would succeed -- but would perform object slicing which prevents the virtual dispatch that you would expect (e.g. it won't behave polymorphically, and any data from the derived class is not present in the base class).
To fix this, you need to change the inheritance to explicitly be public, and you should be using either pointers or references for the dynamic dispatch. For example:
class A
{
public:
virtual void print() = 0;
};
class B : public A
// ^~~~~~
{
public:
void print() override { cout << "foo"; }
};
class C : public A
// ^~~~~~
{
public:
void print() override { cout << "bar"; }
};
To model something closer to the likes of C#, you will want to construct a new object. With the change above to public, it should be possible to use std::unique_ptr (for unique ownership) or std::shared_ptr (for shared ownership).
After this, you can simply do:
int main() {
auto a = std::unique_ptr<A>{nullptr};
auto q = getUserInput();
if (q) { // Note: ternary doesn't work here
a = std::make_unique<B>();
} else {
a = std::make_unique<C>();
}
}
However, note that when owning pointers from an abstract base class, you will always want to have a virtual destructor -- otherwise you may incur a memory leak:
class A {
public:
...
virtual ~A() = default;
};
You can also do something similar with references if you don't want to use heap memory -- at which point the semantics will change a little bit.
References in C++ can only refer to an object that already has a lifetime (e.g. has been constructed), and can't refer to a temporary. This means that you'd have to have instances of B and C to choose from, such as:
int main() {
auto b = B{};
auto c = C{};
bool q = getUserInput();
A& a = q ? b : c;
a.print(); // A& references either 'b' or 'c'
}
You need to use pointers :
A* a = q ? static_cast<A*>(new B) : new C;
...
delete a;
A ternary is also a special case here, as it takes the type of the first expression.
If C inherited from B here it would not be a problem.

Heterogen collection call derived class funtion c++

I have classes A, B, C.
B and C are derived from A. B has a function foo().
If I make an A* array and fill it with B*-s and C*-s then I can't call foo() on the B* element because the compiller will search for it in A.
Is there a way to do it, or A must contain a foo() function too?
The function foo() is only known for B objects. This means that you have a pointer to A, you can't be sure the object has such a function or not. This is why the compiler will complain with an error.
The solution to your issue is polymorphism.
Alternative 1: make the function virtual in A
With this approach, you'd have an empty foo() function that does nothing for all A and C objects, but you'd override with the correct function in B.
Example:
struct A {
virtual void foo () { cout<<"nothing!"<<endl; }
};
struct B : A {
void foo () override { cout<<"this is a B object: foo!"<<endl; }
};
struct C : A {};
int main() {
vector<A*> va;
va.push_back (new A);
va.push_back (new B);
va.push_back(new C);
for (auto x : va)
x->foo();
}
Here the online demo
For the records, I've use a vector of pointers instead of an array. But the principle is the same.
Note also that a rule of thumb is that, if you have a virtual function in a class, you should have a virtual destructor as well (I omit it here for the sake of simplicity).
Alternative 2: make the class polymorphic and use dynamic_cast
With this approach, you'd define the foo() only for B object. The trick is when you iterate through your container, you check if the object is a B (this requires the object to be polymorphic), and if yes, you invoke the function.
Example:
struct A {
virtual ~A() {}; // to make A and its descendents polymorphic, you need at least one virtual function
};
struct B : A {
void foo () { cout<<"this is a B object: foo!"<<endl; }
};
struct C : A {};
int main() {
vector<A*> va;
va.push_back (new A);
va.push_back (new B);
va.push_back(new C);
for (auto x : va) {
auto maybe = dynamic_cast<B*>(x);
if (maybe) // yes, it's a B*
maybe->foo();
else cout << "still not a B"<<endl;
}
return 0;
}
Here the online demo
The dynamic_cast is an intelligent cast: if the type of the object pointed doesn't match the target type, then dynamic_cast returns nullptr.
Alternative 3: not recommended
The last alternative can be considered if A can't be polymorphic, but if you have a mean knowing an A* to determine if the object is in reaity a B or not. This could be the case, if in A you'd have some information about the type of the object. In this case you could consider a static_cast.
This is however not recommended:
you'd have to manage yourself a way to know the type of the object (so you'd manage manually, what the compiler does automatically when the types are polymorphic).
if you'd make an error in your static_cast, i.e. you think the object is a B but in reality it is not, you'd have an undefined behavior.

c++ inheritance abstract function?

I have a somewhat basic question on inheritance that i can seem to figure out, I've done a search and not found what I was looking for so I thought I'd ask here (not sure if title of what I'm looking for is correct).
To keep things simple I've made a bit of example code to illustrate what I'm not getting.
Basically if I have a parent class A and two child classes B & C,
where A contains common stuff (say an id with get/set),
while B & C have functions that are class specific.
If you declare a class B like: A *bObject = new B();
how do you then access the class specific functionbObj->specific()`?
I've tried virtual but that requires both B & C to have the same function name / prototype declared.
I've also tried declaring the abstract in A, but that requires it to be prototype to be in A.
Where am i going wrong here? any help on this, probably basic issue would be helpful.
#include <iostream>
using namespace std;
// A class dec
class A
{
public:
A(void);
~A(void);
char id;
void setId(char id);
char getId();
};
// B class dec - child of A
class B :
public A
{
public:
B(void);
~B(void);
void sayHello();
};
//C class dec - child of A
class C :
public A
{
public:
C(void);
~C(void);
void sayGoodby();
};
//a stuff
A::A(void)
{
}
A::~A(void)
{
}
void A::setId(char id)
{
this->id = id;
}
char A::getId()
{
return this->id;
}
//b stuff
B::B(void)
{
this->setId('b');
}
B::~B(void)
{
}
// c stuff
C::C(void)
{
this->setId('c');
}
C::~C(void)
{
}
void C::sayGoodby()
{
std::cout << "Im Only In C" << std::endl;
}
// main
void main ()
{
A *bobj = new B();
A* cobj = new C();
std::cout << "im class: " << bobj->getId() << endl;
bobj->sayHello(); // A has no member sayHello
std::cout << "im class: " << cobj->getId() << endl;
cobj->sayGoodby(); // A has no member sayGoodby
system("PAUSE");
}
Thank you for your time!
To access methods unique to a derived class, you need to cast the base class pointer to the correct derived class type first (a downcast):
A *bobj = new B();
bobj->sayHello(); // compile error
dynamic_cast<B*>(bobj)->sayHello(); // works
dynamic_cast<C*>(bobj)->sayGoodbye(); // run-time error - probably crashes with a segfault/access violation.
dynamic_cast ensures run-time type safety but adds a small overhead to the cast; for pointer casts, it returns a null pointer if the pointed-to object is not actually a B, and you should check the return value before using it. Alternatively, if you are really sure that the pointer you are casting is pointing to the correct object, you can use static_cast which saves you the cost of the run-time checking, but if the pointer is not pointing to the right object, you get undefined behavior.
A *bobj = new B();
A* cobj = new C();
Here instance of B and C is pointed by pointer of A. Since A have no virtual function for B and C's member function sayHello() and sayGoodbye(), they could not called by bobj->sayHello() and cobj->sayGoodbye(). It is not what polymorphism should be do.
Class A should be:
class A
{
public:
A(void);
~A(void);
char id;
void setId(char id);
char getId();
virtual void sayHello(){/* to do */ };
virtual void sayGoodbye(){ /* to do */ };
};
Then the bobj->sayHello(); and cobj->sayGoodbye(); could be called without complaning.
A *bobj = new B();
The static type of bobj is A *. So, at compile time, the compiler looks for the member functions in the class A definition, what ever you tried to access through bobj. Now,
bobj->sayHello();
the compiler will look for the sayHello in class A since the type of bobj is A *. Compiler doesn't care to look into the class B definition to resolve the call. Since the compiler didn't find it sayHello member in A, it is complaining.
However, the dynamic type of bobj is B * and that is a where call is dispatched depending on the dynamic type.
To resolve the issue, you need to virtual functions of the same in class A.
if you really want to call a function like this, you can do like this:
A* bobj = new B();
((B*)bobj)->sayHello();//this can be dangerous if bobj is not an instance of class B
however, the problem here is you do the design wrongly.
basically, if you create an class A, and subclass it to B and C.
And then assign A* bobj = new B(); you are splitting the interfaces and implementations. That means you will use bobj as if it is an instance of class A. and you will not call the functions in B or C. B & C are implementations of interface class A.
it's just like you hire someone to build your house. You give them your blueprint(interfaces) and hire them to build. you can alter the blueprint as you like, they will do whatever in blueprint. but you can't order them directly(just like you can't call the sayHello() directly from bobj).
You can use a down cast via dynamic_cast<>. You can implement a template method in your base class A to facilitate the down cast:
class A
{
public:
A(void);
virtual ~A(void);
char id;
void setId(char id);
char getId();
template <typename CHILD, typename R, typename... ARGS>
R invoke (R (CHILD::*m)(ARGS...), ARGS... args) {
CHILD *child = dynamic_cast<CHILD *>(this);
if (child) return (child->*m)(args...);
std::cout << "down cast error: " << typeid(CHILD).name() << std::endl;
}
};
If that particular instance of A was not the base of CHILD, then dynamic_cast<CHILD *>(this) result in NULL. Note that the virtual destructor in A is required for the dynamic_cast<> to work.
So, you can use it like this:
std::unique_ptr<A> bobj(new B());
std::unique_ptr<A> cobj(new C());
bobj->invoke(&B::sayHello);
bobj->invoke(&C::sayGoodbye);
cobj->invoke(&B::sayHello);
cobj->invoke(&C::sayGoodbye);
Only the first and last invocations are valid. The middle two will cause the "down cast error" message to be printed.

C++ inheritance: determine inherited methods at runtime

I have a class D that extends B which extends A. I now want to add a class C that has exactly the same interface as B but provides a different implementation. So I design it as the following:
This is not exactly what I want, as I only need an instance of D to either extend B or C and not both, however, this is only determined at runtime. The problem with the design above is of course that if I call a method in D which is implemented both in B and C, its ambiguous.
So what I would like to have is to create an instance of either B or C at runtime and then cast it into D. Every time an instance of D calls an inherited method it should use the one of its original object.
Do I need to fiddle with typeid and if/else around each method call or is there a more elegant way to do this?
class A{
virtual f1();
virtual f2();
}
class B : public virtual A{
f1();
f2();
f3();
}
class C : public virtual A{
f1();
f2();
f3();
}
class D : public B, public C{
f4(){f1(); f3)};
}
...
D* d = new D();
E* e = new E(d);
e->d->f1();
e->d->f4();
Instances of D are then passed to another class (E) which does stuff with D and therefore, I cannot modify the interface of D.
I think you're having inheritance the wrong way around, what you do is define all the methods that you want to call on what you call class D as virtual methods in class A, class B and C both have their own implementation of those methods.
Then you use a data structure of type A*, fill that with pointers to objects of type B and C and you call the methods that you need to call on all the objects in the data structure that contains pointers of type A*, the vtable mechanism will then make sure that the implementation of class B or C is used depending on what the actual object's type is.
See What is the difference between a concrete class and an abstract class?
It sounds like you just want
class A{
virtual void DoMagic() = 0;
};
class B{
virtual void DoMagic(){};
};
class D{
virtual void DoMagic(){};
};
...
bool INeedB = true;//or false
A* a;
if(INeedB){
a= new B();
}else{
a = new C();
}
a->DoMagic(); // will call the appropriate method based on the value of INeedB;
Unless D actually has behavior of its own? Then you can look at decorator pattern, and make D the decorator of an instance of B or C.
Edit: Your D class doesnt need to inherit any of A B or C at all.
class D{
D(A* aObj):a(aObj){}
void f3(){ a->f1();a->f2();}
A *a;
};
Replace A *a in above example with D d
C++ is a statically-typed language. Whatever you do with type declaration is elaborated at compile time, hence the inheritance graph of D cannot be defied at runtime.
What you probably need is to have A as a polymorphic base (with all relevant method virtual, included the destructor) for both B and C (concrete implementation of that), and D an "owner of an A", by containing an A* thet will be assigned at D construction to a new B or new C depending on input.
D destructor will call delete A, and now you have to decide about copy and assignment.
My suggestion is not to use an A*, but a std::unique_ptr (will make the owned object movable between D-s) or std::shared_ptr.
In case you need each D to have its own A, then let A to have a clone method (overridden in B and C, to return a new B and new C respectively) and call it in D's copy ctor and assign operator.
It seems like D doesn't need to inherit from A (or B or C) at all. Instead it just needs to call function in either an instance of B or an instance of C.
You can implement it something like this:
class A
{
public:
virtual void f1();
virtual void f2();
};
class B : public A;
class C : public A;
class D
{
A* b_or_c;
public:
D(A* a_pointer)
: b_or_c(a_pointer)
{}
void f3()
{
b_or_c->f1();
b_or_c->f2();
}
};
Can be used like this:
B b; // An instance of B
C c; // An instance of C
D d1(&b);
D d2(&c);
d1.f3(); // Will cause `f1` and `f2` in the object `b` to be called
d2.f3(); // Will cause `f1` and `f2` in the object `c` to be called

c++ problem with function overloading

i have a problem with function overloading. I will show you with some simple example:
class A {};
class B : public A{};
void somefunction(A&, A&);
void somefunction(B&, B&);
void someotherfunction() {
...
A& a1 = ...
A& a2 = ...
...
}
Both a1 and a2 are instances of B but
somefunction(a1,a2);
calls
void somefunction(A&, A&);
What did i do wrong? I mean polymorphism and overloading are for stuff like that, arent they?
edit: Ok now i know it does not work (thanks for your answers).
Any solution how to do this? Without casting.
edit2: Ok left it as it is, with type casting, since something i would like to have is not possible. Thanks all for your help.
Cast them statically so that the compiler knows which one to pick:
void somefunction((B&)a1, (B&)a2);
The reason why you are having this problem is with the program design, not the language. Compiler picks which which function is used based on the types that are passed in. C# will behave in exactly the same way (pretty sure Java will too).
It seems to me that you are implementing polymorphism in the wrong place. somefunction really belongs inside class a and should be virtual. Then whenever it's called on the instance of a at runtime the override in the right class will be called.
So, really it should be something like this:
class a {
public:
virtual somefunction(a& a2) {
//do stuff
}
}
class b : public a {
virtual somefunction(a& a2) {
b& b2 = (b&)a2;
//do stuff
}
}
class c : public b {
virtual somefunction(a& a2) {
c& c2 = (c&)a2;
//do stuff
}
}
The above solution uses minimal casting inside the virtual function and assumes that the two instance of the same type. This means that b.somefunction(a()) will have undefined behaviour.
A better solution is to rely on C++ RTTI and use dynamic_cast, which will return NULL if the downcast is not possible.
This problem is known as double dispatch problem and is described in the wikipedia article pretty much as you described it. Furthermore, the only solution that wikipedia gives for multiple dispatch is to use dynamic_cast.
EDIT OK, this has been bugging me, here is the solution for full double dispatch between a base class and two subclasses. It aint pretty and uses a bit of C++ trickery like friend classes (for better encapsulation actually, rather than the reverse) and forward declarations.
class b;
class c;
class a {
protected:
virtual void somefunction(a& a2); //do stuff here
virtual void somefunction(b& b2); //delegate to b
virtual void somefunction(c& c2); //delegate to c
public:
virtual void doFunc(a& a2) {
a2.somefunction(*this);
}
friend class b;
friend class c;
};
class b : public a {
protected:
virtual void somefunction(a& a2); //do stuff here
virtual void somefunction(b& b2); //do stuff here
virtual void somefunction(c& c2); //delegate to c
public:
virtual void doFunc(a& a2) {
a2.somefunction(*this);
}
friend class a;
};
class c : public b {
protected:
virtual void somefunction(a& a2); //do stuff here
virtual void somefunction(b& b2); //do stuff here
virtual void somefunction(c& c2); //delegate to c
public:
virtual void doFunc(a& a2) {
a2.somefunction(*this);
}
friend class a;
friend class b;
};
//class a
void a::somefunction(a& a2) {
printf("Doing a<->a");
}
void a::somefunction(b& b2) {
b2.somefunction(*this);
}
void a::somefunction(c& c2) {
c2.somefunction(*this);
}
//class b
void b::somefunction(a& a2) {
printf("Doing b<->a");
}
void b::somefunction(b& b2) {
printf("Doing b<->b");
}
void b::somefunction(c& c2) {
c2.somefunction(*this);
}
//class c
void c::somefunction(a& a2) {
printf("Doing c<->a");
}
void c::somefunction(b& b2) {
printf("Doing c<->b");
}
void c::somefunction(c& c2) {
printf("Doing c<->c");
}
The function to call is only determined at run-time for virtual methods, based on the type of the this object:
A* a = new B;
a->foo(); //calls B::foo (as long as foo is virtual)
The function to call is not resolved at run-time based on the "real" type of a function's arguments.
A* a = new B;
X* x = new Y;
a->foo(x); //assuming virtual and two overloads, calls B::foo(X*), not B::foo(Y*)
There is no built-in double dispatch mechanism (to select the function to call based on the dynamic types of two objects at the same time), although the pattern can be manually implemented as some posts show.
If you say that you always know that the A& will actually be B& and don't want casts, I conclude that the types will be hard-coded known at compile-time, so you might try "compile-time polymorphism" instead. (In this case A and B don't even need to be related, as long as they have a suitable interface.)
class A {};
class B {};
class C: public A {};
void somefunction(const A&, const A&);
void somefunction(const B&, const B&);
template <class T>
void someotherfunction()
{
const T& a1 = T();
const T& a2 = T();
somefunction(a1, a2);
}
int main()
{
someotherfunction<A>();
someotherfunction<B>();
//combine with inheritance and it will still be
//possible to call somefunction(A&, A&) since
//somefunction(C&, C&) is not defined
someotherfunction<C>();
}
Now a1 and a2 will really be As in one instantiation and Bs in the other case, as far as selecting the overload is concerned. (I added some consts, because otherwise it would be harder to produce something that binds to non-const references.)
As others have already mentioned, the compiler picks the correct overload - its how the language works.
If you are really sure of what type the instances are, you should just cast. If not, one way you can get around manual type-checking at run-time is double dispatch:
struct A;
struct B;
struct Base {
virtual perform(Base& b) = 0;
virtual perform(A& a) = 0;
virtual perform(B& b) = 0;
};
struct A : Base {
virtual perform(Base& b) { b.perform(*this); }
virtual perform(A& a) { someFunction(a, *this); }
virtual perform(B& b) { someFunction(b, *this); }
};
struct B : A {
virtual perform(Base& b) { b.perform(*this); }
virtual perform(A& a) { someFunction(a, *this); }
virtual perform(B& b) { someFunction(b, *this); }
};
// ...
Base& b1 = foo1();
Base& b2 = foo2();
b1.perform(b2);
what exactly are you trying to do? it looks like you are trying to write a function that does something given two objects, and you want it to do a different thing based on the type of the combination of objects?
remember that even normal polymorphism does "checks" internally.
this is an interesting problem tho,
polymorphism gives you the ability to easily overload the functionality of a function based on the type of ONE object, not two.
what is it EXACTLY that you are trying to do? my best suggestion would be to make it so that each object could perform its own specific stuff separately and then return a common object for common processing:
class Base
{
virtual SomeComonInterfaceObject DoMySpecialSomething() = 0;
}
void _doSomething(SomeComonInterfaceObject a, SomeComonInterfaceObject b);
void doSomething(Base& o1, Base& o2)
{
_doSomething(o1->DoMySpecialSomething(), o2->DoMySpecialSomething());
}
if that doesn't suit, you probably just have to check the type and do specifics based on that.
note that even normal polymorphism does "checks" if you are worried about performance, any other language would have to too.
the only way you might be able to get around that is by using templates, and it would probably get real ugly.
would be interesting to know what you are trying to do. also, these doSomething functions, is it always the case that their two parameters are the same type? or do they mix and match?
Yes but C++ decided which function to use at compile time, not at runtime. And at compile time the only thing the compiler sees is (A&, A&) - it cannot know that those are actually instances of B.
You should post more code....what is
A& a1 = ...
A& a2 = ...
Shouldn't you use pointers?
If you're storing a1 and a2 as type A then even if they are also B's the A overload gets called. You'd have to dynamic_cast them.
In this case compiler will always call somefunction(A&, A&);. Why would it call somefunction(B&, B&);?
You said in a comment that you're SURE that they are B's.
If that is the case then this is what you want to do.
B a1();
B a2();
If you ever need A's, you can do this (A*)&B. That is an implicit cast and I'm pretty sure it happens at compile time.
Your compiler has chosen what it thinks is the most appropriate overload. a1 and a2 are both declared as references to class A, so they fit the overload which takes references to class A "better" than they fit the other one, since that would require some sort of implicit cast to convert them to class B.
Note also that you can't implicitly upcast that way. If you have a pointer or reference to an instance of the base class (A in this case) then it can't be implicitly converted to a derived class, because in general not all instances of the base class are instances of the derived class (all Bs are As, but not all As are Bs).
You will need to declare them as instances of B before calling the function:
B& b1 = ...
B& b2 = ...
somefunction(b1, b2);
What i will do is to use a dispatch table to get what i want. Instead of 1 dimensional it may be 2 or 3 dimensional (probably 2). Thanks all for trying to help me!