C++ multiple inheritance and cross delegation with void*? - c++

class Base1
{
public:
virtual ~Base1(){}
virtual void whatever()
{
cout << "whatever" << endl;
}
};
class Base2
{
public:
virtual ~Base2(){}
virtual void aFunc(int i) = 0;
};
class A : public Base1, public Base2
{
public:
A()
{}
~A()
{}
virtual void aFunc(int i) final
{
cout << "func" << endl;
}
};
int main()
{
void* a;
a = new A();
(static_cast<Base2*>(a))->aFunc(0);
Base2* ptr = static_cast<Base2*>(a);
ptr->aFunc(0);
return 0;
}
This example prints out "whatever" instead of "func", if I change the line with void* to A* than it prints out "func". Is this a known behavior? I would expect that's the case just don't know why.

Is this a known behavior?
Yes. Behaviour is well-defined if you convert to void* and then back to the same type. It's undefined if you convert back to a different type.
I would expect that's the case just don't know why.
There's no guarantee that a base sub-object has the same address as the complete object; in fact, if there's more than one non-empty base class, then at least one sub-object will have to be at a different address. So a valid conversion from A* to Base2* probably needs to adjust the value of the pointer, not just reinterpret it as a different type. Conversion to void* and back can't make that adjustment.

Related

C++ cast pointer to base class pointer for virtual method call

I have the following code:
struct A
{
virtual void foo() {std::cout << "A\n";}
};
struct B : public A
{
virtual void foo() {std::cout << "B\n";}
};
void bar(A * a)
{
a->foo();
}
Without changing this code, is it possible to cast bp pointer to B, so calling bar would print "A"?
int main()
{
B * bp = new B();
bar(/* do somethig*/ bp);
return 0;
}
Tried every cast I remebered:
int main()
{
B * bp = new B();
bar((A*)bp);
bar(static_cast<A*>(bp));
bar(reinterpret_cast<A*>(bp));
bar(dynamic_cast<A*>(bp));
return 0;
}
You could make a shim wrapper around B, and have the shim's virtual function dispatched to BWrap::foo() call directly to A::foo();.
There's not really any point in the example to carrying along the B& member variable reference, but for more interesting examples there may be a use case.
struct BWrap : public A
{
B& b;
BWrap(B& bb) : b{bb} {}
virtual void foo() { b.A::foo(); }
};
int main()
{
B* bp = new B();
BWrap bw{*bp};
bar(&bw);
}
If you insist on the A object being a base class subobject of a B object and on not modifying the first code snippet at all, then the only solution is to add an even more derived class that can override the virtual call as explained in the answer by #Eljay (which I completely forgot to think about when first writing this answer).
Other options are to create a complete A object, not a B object, or to modify bar to do a call without virtual dispatch by using a qualified name:
a->A::foo();
All of the casts you are showing have the same effect as the implicit conversion, except for reinterpret_cast which will cause undefined behavior when used this way.

C++ unexpected calling of function of inherited classes

I made following 3 classes:
struct Parent1
{
virtual void f()
{
cout << "\nParent1::f";
}
};
struct Parent2
{
virtual void g()
{
cout << "\nParent2::g";
}
virtual void z()
{
cout << "\nParent2::z";
}
};
struct Child : public Parent1, public Parent2
{
virtual void h()
{
cout << "\nChild::h";
}
};
In main, when I call function z of Parent2, it instead calls function h of the child class. Why is it happening so?
Following is the main function:
int main()
{
Child obj;
Parent2 * p2 = (Parent2*)(Parent1*)&obj;
p2->z();
return 0;
}
The first explicit conversion from &obj i.e. Child* to Parent1* is an upcast. The result will point to the base class sub-object. The next explicit conversion is from Parent1* to Parent2*. Since these classes are not directly related, this is a reinterpretation cast. But the types are not pointer-interconvertible, so when you call the function through the reinterpreted pointer, the behaviour of the program is undefined.
You should avoid using C-style casts to prevent mistakes like this. In this case, no explicit cast is needed at all. This works correctly:
Parent2 * p2 = &obj;
And never reinterpret pointers unless you know what it means and that it is OK to do so.

Why is not overloaded function for derived class object invoked when given a pointer to base class in C++?

In the following code
#include <iostream>
using namespace std;
class A {
public:
A() {}
virtual ~A() {};
};
class B : public A {
public:
B() {}
virtual ~B() {};
};
void process(const A&) {
cout << "processing A" << endl;
}
void process(const B&) {
cout << "processing B" << endl;
}
int main(void) {
A* a = new B;
process(*a);
return 0;
}
the output of running it becomes
processing A
but I would have assumed that it should have been
processing B
since a points to the derived class B and not A. So why does it call the first implementation of process function and not the second?
The static type of expression *a is A because a was declared as
A* a = new B;
The compiler resolves the selection of overloaded functions using the static type of the argument.
Even when virtual functions are called the compiler uses the static type of the object to call appropriate function. The difference is only that the compiler uses the table of pointers to virtual functions to indirectly call the required function.
You need to make process() a virtual member function of A, B:
class A {
public:
A() {}
virtual ~A() {};
virtual void process() const { cout << "processing A" << endl; }
};
class B : public A {
public:
B() {}
virtual ~B() {};
virtual void process() const override { cout << "processing B" << endl; }
};
int main(void) {
A* a = new B;
a->process();
return 0;
}
In your current code, *a is of type A&, so the closest match to process(*a); is the first overload (for const A&).
void process(const A&); is a better (exact) match, since dereferencing A* gives you A&.
Short answer, but there isn't much more to say unless you want a reference from the standard.
You could dynamic_cast the result of *a and that would give you a B&, but that's smelly desing. What you probably want is a virtual function in A that's overriden in B (assume it's called foo). Then, calling a->foo() would dispatch to B::foo.

why doesn't dereferencing a polymorphic pointer call derived type argument in a function?

i do not understand why this behavior occurs:
class Base
{
public:
virtual void enablePolymorphism();
};
class Derived : public Base
{
public:
void enablePolymorphism();
};
class Derived2 : public Base
{
public:
void enablePolymorphism();
};
void callMe(Base base)
{
printf("base");
}
void callMe(Derived derived)
{
printf("derived");
}
void callMe(Derived2 derived2)
{
printf("derived2");
}
int main()
{
Base* pointer = new Derived();
Base* pointer2 = new Derived2();
callMe(*pointer);
callMe(*pointer2);
return 0;
}
this is what i actually want my code to do and i want the method callMe() to be outside the classes therefore i cannot use virtual functions, i want at run-time for the program to call callMe(Derived derived) when i do callMe(*pointer) and callMe(Derived2 derived2) when i do callMe(*pointer2) for which the output would be derivedderived2 but that's not what happens, at compile-time pointer and pointer2 are assumed to be of Base class when dereferenced so the callMe(Base base) is called instead and the output is basebase. How do i achieve the output i want? thank you.
void callMe(A);
void callMe(B);
A*ptr;
callMe(*ptr); // guess which of the above is called?
this has nothing to do with polymorphism, but is simple overloading resolution.
Runtime polymorphism applies only to member functions that are marked with the virtual keyword (or that override a virtual member function):
virtual void callMe();
For a non-member function, or a non-virtual member function, the appropriate overload is selected at compile time based on the declared type (not the runtime type) of the argument(s).
The only thing the compiler sees is that the expression *pointer is of type Base& and therefore succeeds into choosing the correct overload callMe(Base) for the function.
In your case, you can use a polymorphic function instead:
#include <memory>
#include <iostream>
class Base {
public:
virtual void callMe() { std::cout << "called base"; }
};
class Derived : public Base {
public:
virtual void callMe() { std::cout << "called derived"; }
};
int main() {
std::unique_ptr<Base> pointer(new Derived());
pointer->callMe();
return 0;
}
And here is the live example.

Calling a subclass method. Pointer vs non-pointer

I have the following code:
main.hxx:
#include <iostream>
class Base{
public:
Base() {}
~Base() {}
virtual void whoAreYou() { std::cout << "I am base!" << std::endl;}
};
class Sub : public Base{
public:
Sub() {}
~Sub() {}
virtual void whoAreYou() { std::cout << "I am Sub!" << std::endl;}
};
class Factory {
public:
static Base getBase() { return Base(); }
static Base* getBasePtr() { return new Base(); }
static Base getSub() { return Sub(); }
static Base* getSubPtr() { return new Sub(); }
};
main.cxx
#include "main.hxx"
int main (int argc, char **argv) {
// Non pointers
Factory::getBase().whoAreYou();
Factory::getSub().whoAreYou();
// Pointers
Base* basePtr = Factory::getBasePtr();
Base* subPtr = Factory::getSubPtr();
basePtr->whoAreYou();
subPtr->whoAreYou();
delete basePtr, subPtr;
return 0;
}
When run, it prints the following:
I am base!
I am base!
I am base!
I am Sub!
I was expecting "Factory::getSub().whoAreYou();" to print "I am Sub!". Is it because when not using a pointer it gets casted to a Base?
I was expecting Factory::getSub().whoAreYou(); to print "I am Sub!".
No, the function returns a Base, so a Base is what you get.
Is it because when not using a pointer it gets casted to a Base?
Yes (although the word is "converted" not "casted" - a cast is an explicit conversion, and this conversion is implicit). This is sometimes called "slicing", since the derived-class part of the object is "sliced off" when it's copied.
Also, beware that the following:
delete basePtr, subPtr;
only deletes subPtr. You need a separate delete expression for each. You also need a virtual destructor in Base to safely delete subPtr.
This line creates a Sub then call Base default copy constructor to create a instance of Base from a the instance Sub:
static Base getSub() { return Sub(); }
Hence your log.
More generaly a Base is a Base instance, whereas Base* is a pointer on a Base instance or an object that inherits Base.