I was looking to create a function that is capable of working with any Derived Object of A.
However in this example, I can't seem to be able to use B Object in a function that has a A Typing on it. Is there any way I pass B into the Function?
class A {
public:
A() {
}
};
class B :A {
public:
B() {
}
};
void function(A a) {
return;
}
int main(void) {
B b();
function(b);
}
I've commented on the fixes needed inline:
class A {
public:
A() {}
};
class B : public A { // public inheritance or A will be an inaccessible base of B
public:
B() {}
};
void function(const A& a) { // take a reference to an A to avoid copy-slicing
// ... work with the A part of the object you reference with `a`
}
int main() { // void not needed (but not an error as such)
B b; // not a function declaration anymore
function(b);
}
Actually you are lucky. You made two mistakes that caused passing b to the function fail, while in fact without that other mistakes you can pass b to the function but it would do the wrong thing silently.
First the two mistakes: B b(); declares a function. To declare a default constructed B you write B b;. Then B inherits privately, hence you cannot convert a B to an A. Thats what the error your code causes have told you.
However, after fixing those (and removing user declared constructors taht shouldnt be there when they do nothing)...
class A {};
class B : public A {};
void function(A a) {}
int main(void) {
B b;
function(b); // object slicing !!
}
This code compiles without errors, but usually it does the wrong thing!
Any B can be converted to an A because the inheritance is public, but what happens is object slicing: What is object slicing?. If B had any members not in A then they would all be lost when passing it to function. Its not an issue here because neither A nor B have any members, but in general you want to avoid objects to get sliced.
TL;DR: References / pointers are needed for polymorphism. Pass by (const) reference:
void function(const A& a) {} // does not modify a
void function(A& a) {} // modifies a
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.
Yesterday, I wrote some code and i would really appreciate a judgement if this is good or bad practice. And if its bad, what could go wrong.
The construct is as followed:
The base class A comes from an API sadly as a template. The goal was to be able to put derived classes from A in a std::vector. I achieved this with the base class B from which all derived classes that inherit from A will inherit. Without the pure-virtual function in B the foo() function from A was called.
With the pure-virtual function in B the foo() version from C get called. This is exactly what I want.
So is this bad practice?
EDIT:
To clear some misunderstandings in my example code out:
template <class T>
class A
{
public:
/* ctor & dtor & ... */
T& getDerived() { return *static_cast<T*>(this); }
void bar()
{
getDerived().foo(); // say whatever derived class T will say
foo(); // say chicken
}
void foo() { std::cout << "and chicken" << std::endl; }
};
class B : public A<B>
{
public:
/* ctor & dtor */
virtual void foo() = 0; // pure-virtual
};
class C : public B
{
public:
/* ctor & dtor */
virtual void foo() { std::cout << "cow"; }
};
class D : public B
{
public:
/* ctor & dtor */
virtual void foo() { std::cout << "bull"; }
};
The std::vector shall contain both, C as well as D and
void main()
{
std::vector<B*> _cows;
_cows.push_back((B*)new C()));
_cows.push_back((B*)new D()));
for(std::vector<B*>::size_type i = 0; i != _cows.size(); ++i)
_cows[i].bar();
}
with output
cow and chicken
bull and chicken
is desired.
As far as I know is there no other way to store classes derived from a template class in a container than the use of a base class. If I use a base class for my derived classes, e.g., B i must cast every instance within the vector back to its proper class. But at the time bar() is called, I don't know the exact type.
I call it bad practice for doing possibly confusing and obfuscating things.
1) A function name should in all base and sub-classes either be virtual or non-virtual.
mixing overriding and overloading within the inheritance hierachry is a very bad idea.
No one really expects something like that.
Thus if A::foo should be virtual as well, or B and C foo should not.
2) Preferably base classes should be interfaces.
As such A:foo should be pure virtual and not B::foo.
2b) If a base class has already provided a default implementation don't declare the function pure virtual in a sub-class.
The following question might look like a duplicate but I couldn't find the exact idea anywhere else in the site.
A brief introduction: This question raised as I was trying to understand a little more complexity inheritance combination in my class.
One note before I present the question - I don't look for a sort of "Solution", only wish to discuss with you about the topic and acquire a better thinking.
Suppose you have the following lines:
class C : public B
{
public :
C (const B& b) : B (b) {}
B& operator*() {return *this;}
};
int main() {
A* pA = new B();
C& c = pA -> doIt();
*c = *pA;
c = *pA;
return 1;
}
This code isn't full and this is the whole purpose - assume it does complie and extract the constraints in this code.
Still I wouldn't just write a code and ask you to explain any constraint of the top off your head but instead I will add my concreate question:
What constraints do we have for the following line :
C& c = pA -> doIt();
As far as I understand, the above code has one staring constraint which is the hierarchy order of these class : C is derived of B and B is dervied of A (correct me If I'm wrong..)
I was trying to actually define these classes while keeping the hierarchy I described above, and I couldn't have doIt() to return a type of its derived class C. I can use incomplete type C& in the prototype of an A function but yet I cannot return an object of type C.
Thank you in advance,
SyndicatorBBB
Try this:
class C;
struct A
{
C & doIt();
};
struct B : A
{
void operator=(A const &) { }
};
class C : public B
{
public :
using B::operator=;
C (const B & b) : B(b) {}
B & operator*() { return *this; }
};
C & A::doIt()
{
static B bimpl;
static C cimpl(bimpl);
return cimpl;
}
Note that the implicit assignment operator hides the base version, so we need explicit unhiding of the operator with the using declaration.
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!