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!
Related
What I would like, if not with this syntax, but in spirit :
class A
{
virtual A f()=0;
};
class B : public A
{
B f();
};
I do see the problem with the code above : A is virtual, thus no instance of A can be created, hence no instance of A can be returned.
Yet, concrete subclasses of A (e.g. B) will have to implement the function f, which will always be able to return an instance of themselve (e.g. instance of B), i.e. an instance of a subclass of A.
While the above is incorrect and does not compile, is there a way to get something similar valid ?
Possibly, but not necessarily, of the like:
class A
{
virtual "a concrete sublclass of A" f()=0;
};
note: I prefer not to return a pointer or a reference, as I would prefer B not to have to manage an instance of itself as attribute.
note: if possible c++11, but curious to hear about newer versions as well
Your attempted solution risks object slicing. Copying a B as an A will probably not work the way you expect. In general, it's best to avoid value semantics when dealing with polymorphic types. Consider returning a std::unique_ptr<A> instead :
#include <memory>
class A
{
public:
virtual std::unique_ptr<A> f()=0;
};
class B : public A
{
public:
std::unique_ptr<A> f() override;
};
This requires C++11. It will behave the way you expect and the user won't have to manage the lifetime of the resulting object.
However, contrary to what was shown in the original code, B::foo() won't give you access to the full interface of a B. It's not clear to me if this is required or not. If it is, you will need an extra layer. For example, define a g() that returns std::unique_ptr<B> which f() calls :
class B : public A
{
public:
std::unique_ptr<A> f() override { return g(); }
std::unique_ptr<B> g();
};
It looks like you're trying to write a factory or clone function of sorts. This is commonly done using std::unique_ptr to cleanly pass ownership of the created object to the caller:
class A
{
virtual std::unique_ptr<A> f() = 0;
};
class B : public A
{
std::unique_ptr<A> f() override;
};
Demo
The only downside is that you cannot have B::f return a std::unique_ptr<B> as that's not covariant with std::unique_ptr<A> (even though it implicitly converts to it).
note: if possible c++11, but curious to hear about newer versions as well
No. that is not possible. You can return a covariant type in a derived class though.
If the return type in the base classs is A&, it is ok to return B& in B.
If the return type in the base classs is A*, it is ok to return B* in B.
class A
{
virtual A& f()=0;
virtual A* g()=0;
};
class B : public A
{
B& f();
B* g()=0;
};
Write something like
class A
{
virtual const A& f() const = 0;
};
class B : public A
{
const B& f() const override { return *this; }
};
Instead of reference you may use pointers.
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.
Suppose I have the class
class A {
protected:
int x,y;
double z,w;
public:
void foo();
void bar();
void baz();
};
defined and used in my code and the code of others. Now, I want to write some library which could very well operate on A's, but it's actually more general, and would be able to operate on:
class B {
protected:
int y;
double z;
public:
void bar();
};
and I do want my library to be general, so I define a B class and that's what its APIs take.
I would like to be able to tell the compiler - not in the definition of A which I no longer control, but elsewhere, probably in the definition of B:
Look, please try to think of B as a superclass of A. Thus, in particular, lay it out in memory so that if I reinterpret an A* as a B*, my code expecting B*s would work. And please then actually accept A* as a B* (and A& as a B& etc.).
In C++ we can do this the other way, i.e. if B is the class we don't control we can perform a "subclass a known class" operation with class A : public B { ... }; and I know C++ doesn't have the opposite mechanism - "superclass a known class A by a new class B". My question is - what's the closest achievable approximation of this mechanism?
Notes:
This is all strictly compile-time, not run-time.
There can be no changes whatsoever to class A. I can only modify the definition of B and code that knows about both A and B. Other people will still use class A, and so will I if I want my code to interact with theirs.
This should preferably be "scalable" to multiple superclasses. So maybe I also have class C { protected: int x; double w; public: void baz(); } which should also behave like a superclass of A.
You can do the following:
class C
{
struct Interface
{
virtual void bar() = 0;
virtual ~Interface(){}
};
template <class T>
struct Interfacer : Interface
{
T t;
Interfacer(T t):t(t){}
void bar() { t.bar(); }
};
std::unique_ptr<Interface> interface;
public:
template <class T>
C(const T & t): interface(new Interfacer<T>(t)){}
void bar() { interface->bar(); }
};
The idea is to use type-erasure (that's the Interface and Interfacer<T> classes) under the covers to allow C to take anything that you can call bar on and then your library will take objects of type C.
I know C++ doesn't have the opposite mechanism - "superclass a known
class"
Oh yes it does:
template <class Superclass>
class Class : public Superclass
{
};
and off you go. All at compile time, needless to say.
If you have a class A that can't be changed and need to slot it into an inheritance structure, then use something on the lines of
template<class Superclass>
class Class : public A, public Superclass
{
};
Note that dynamic_cast will reach A* pointers given Superclass* pointers and vice-versa. Ditto Class* pointers. At this point, you're getting close to Composition, Traits, and Concepts.
Normal templates do this, and the compiler will inform you when you use them incorrectly.
instead of
void BConsumer1(std::vector<B*> bs)
{ std::for_each(bs.begin(), bs.end(), &B::bar); }
void BConsumer2(B& b)
{ b.bar(); }
class BSubclass : public B
{
double xplusz() const { return B::x + B::z; }
}
you write
template<typename Blike>
void BConsumer1(std::vector<Blike*> bs)
{ std::for_each(bs.begin(), bs.end(), &Blike::bar); }
template<typename Blike>
void BConsumer2(Blike& b)
{ b.bar(); }
template<typename Blike>
class BSubclass : public Blike
{
double xplusz() const { return Blike::x + Blike::z; }
}
And you use BConsumer1 & BConsumer2 like
std::vector<A*> as = /* some As */
BConsumer1(as); // deduces to BConsumer1<A>
A a;
BConsumer2(a); // deduces to BConsumer2<A>
std::vector<B*> bs = /* some Bs */
BConsumer1(bs); // deduces to BConsumer1<B>
// etc
And you would have BSubclass<A> and BSubclass<B>, as types that use the B interface to do something.
There is no way to change the behaviour of a class without changing the class. There is indeed no mechanism for adding a parent class after A has already been defined.
I can only modify the definition of B and code that knows about both A and B.
You cannot change A, but you can change the code that uses A. So you could, instead of using A, simply use another class that does inherit from B (let us call it D). I think this is the closest achievable of the desired mechanism.
D can re-use A as a sub-object (possibly as a base) if that is useful.
This should preferably be "scalable" to multiple superclasses.
D can inherit as many super-classes as you need it to.
A demo:
class D : A, public B, public C {
public:
D(const A&);
void foo(){A::foo();}
void bar(){A::bar();}
void baz(){A::baz();}
};
Now D behaves exactly as A would behave if only A had inherited B and C.
Inheriting A publicly would allow getting rid of all the delegation boilerplate:
class D : public A, public B, public C {
public:
D(const A&);
};
However, I think that could have potential to create confusion between code that uses A without knowledge of B and code that uses knows of B (and therefore uses D). The code that uses D can easily deal with A, but not the other way 'round.
Not inheriting A at all but using a member instead would allow you to not copy A to create D, but instead refer to an existing one:
class D : public B, public C {
A& a;
public:
D(const A&);
void foo(){a.foo();}
void bar(){a.bar();}
void baz(){a.baz();}
};
This obviously has potential to mistakes with object lifetimes. That could be solved with shared pointers:
class D : public B, public C {
std::shared_ptr<A> a;
public:
D(const std::shared_ptr<A>&);
void foo(){a->foo();}
void bar(){a->bar();}
void baz(){a->baz();}
};
However, this is presumably only an option if the other code that doesn't know about Bor D also uses shared pointers.
This seems more like static polymorphism rather dynamic. As #ZdeněkJelínek has already mentioned, you could you a template to ensure the proper interface is passed in, all during compile-time.
namespace details_ {
template<class T, class=void>
struct has_bar : std::false_type {};
template<class T>
struct has_bar<T, std::void_t<decltype(std::declval<T>().bar())>> : std::true_type {};
}
template<class T>
constexpr bool has_bar = details_::has_bar<T>::value;
template<class T>
std::enable_if_t<has_bar<T>> use_bar(T *t) { t->bar(); }
template<class T>
std::enable_if_t<!has_bar<T>> use_bar(T *) {
static_assert(false, "Cannot use bar if class does not have a bar member function");
}
This should do what you'd like (i.e. use bar for any class) without having to resort to a vtable lookup and without having the ability to modify classes. This level of indirection should be inlined out with proper optimization flags set. In other words you'll have the runtime efficiency of directly invoking bar.
I have a problem with my code.
class A{
virtual foo()=0;
}
class B: public A {
foo();
foo2();
operator X(A * a) {a->foo2()} //doesn't work
}
class C: public A {
foo();
foo2();
operator X(A * a) {a->foo2()} //doesn't work.
}
So I have a virtual class, and 2 classes that inherit from it. And I have to define an operator X that acts on an A object, no matter if it is B or C (since it can't be A because A is abstract). The problem is that the operator calls foo2(), which I'm not allowed to write in class A. What should I do?
Thanks a lot for helping me. This is my first post.
The right answer is to declare foo2 pure virtual in A. However you have been told you are not allowed to do this. Boo :-(
Your only remaining option is to use dynamic_cast.
void do_foo2(A* a)
{
if (B* b = dynamic_cast<B*>(b))
return b->foo2();
C& c = dynamic_cast<C&>(*a); // Will throw if a is not B or C.
return c.foo2();
}
Then
void B::operator X(A* a)
{
do_foo2(a);
}
Note: This all assumes you are supposed to make B::operator X work with both B and C.
I have a base container class, which has a number of operators (=,+,-,+=,etc). It is expected that the logic of the operators will not need to be changed for the derived classes. Thus, ideally, I would like to use the base class operators for all of its derived classes without having to redefine them for each of the derived classes explicitly (with the exception of the assignment operator).
A solution that I came up with is demonstrated below based on a simple example. The solution seems to work, but I have doubts about the validity of the method for more complicated cases. Do you think it is valid to use this assignment "hack" in class B? What are the potential pitfalls of this method? Is there anything I missed? Are there easier ways of achieving the functionality that I need (i.e. using base class operators for derived classes)?
class A
{
protected:
int a;
public:
A(int ca)
{
a=ca;
}
A(const A& A1)
{
a=A1.a;
}
int geta() const
{
return a;
}
void seta(int ca)
{
a=ca;
}
const A& operator=(const A& A1)
{
a=A1.a;
return *this;
}
};
const A operator+(const A& A1, const A& A2)
{
A myA(A1.geta()+A2.geta());
return myA;
}
class B: public A
{
public:
B(int a): A(a) {}// ... using A::A;
const B& operator=(const B& B1)
{
a=B1.geta();
return *this;
}
const B& operator=(const A& B1)
{
a=B1.geta();
return *this;
}
};
int main()
{
B myB(4);
A myA(3);
//need this to work
myB=myB+myB;
cout << myB.geta();
myA=myA+myA;
cout << myA.geta();
int j;
cin >> j;
}
For the example given i don't see any problems that can happen. Of cause you can improve the code, first by returning non const reference in operator=, second i think by adding += op to your class, and using it's code inside global operator+ function.
But in general i think it should work fine. As for assignment operators - as soon as you have only POD types and no pointers, or references or handles you don't really need any.
It will become more complicated, however when pointers appear. You'll need to make sure you copy objects, pointed by them, or manage them some other way.
And you probably will not need to modify your operators as long as you don't add more members to derived classes, which also should take part in calculations.
In general you don't have to redefine functions in the base class for derived classes. With public inheritance your derived classes will have access to those functions and use their operation just fine. If you do want to re-define them (= operator for example), be sure you call the right one (virtual functions help in this case).