C++ Dynamic binding in method argument - c++

I recently wanted to get c++ to dynamically resolve a member/function by its input parameter which comes in some derived versions. Here is what I mean:
#include <iostream>
class Base {
};
class DerivedA : public Base {
};
class DerivedB : public Base {
};
class DerivedC : public Base {
};
class Test {
public:
void world( DerivedA *instance )
{
std::cout << "DerivedA" << std::endl;
}
void world( DerivedB *instance )
{
std::cout << "DerivedB" << std::endl;
}
void world( Base *instance )
{
std::cout << "Base" << std::endl;
}
};
int main()
{
Base *a = new Base;
Base *b = new DerivedA;
Base *c = new DerivedB;
Base *d = new DerivedC;
Test hello;
hello.world( a );
hello.world( b );
hello.world( c );
hello.world( d );
return 0;
}
The behaviour I WANTED is this:
Base
DerivedA
DerivedB
Base
But for sure the output I am REALLY getting is this:
Base
Base
Base
Base
I understand, that dynamic binding is the other way, resolving the correct member function within the derived classes of base and not like that way - but can it work in any way for that?
Maybe I am only missing the essential point..
However, many thanks in advance!
Sebastian

The type of a, b, c and d are all Base*. The compiler does not track "what the variable contains". If that is what you want to do then you need to use a virtual function in the class that you derive from, for example:
class Base {
public:
virtual const char* MyName() { return "Base"; }
};
class DerivedA : public Base {
public:
virtual const char* MyName() { return "DerivedA"; }
};
... similiar for all derived classes ...
void world( Base *instance )
{
std::cout << instance->MyName() << std::endl;
}
(Edit: To get exactly the behaviour you list in the first case, you'd need to NOT implement the MyName() function in the DerivedC class)
So, using a wrapper class may be the solution for a test-setup. Here's something I just hacked up, without much consideration and sophistication:
#include <iostream>
class Base {
};
class DerivedA : public Base {
};
class DerivedB : public Base {
};
class DerivedC : public Base {
};
class Test {
public:
void world( DerivedA *instance )
{
std::cout << "DerivedA" << std::endl;
}
void world( DerivedB *instance )
{
std::cout << "DerivedB" << std::endl;
}
void world( Base *instance )
{
std::cout << "Base" << std::endl;
}
};
template<typename T>
class Wrapper
{
public:
Wrapper(T* i) : instance(i)
{
}
~Wrapper()
{
delete instance;
}
void doTest(Test& t)
{
t.world(instance);
}
T* instance;
};
int main()
{
Test hello;
Wrapper<Base> a(new Base);
Wrapper<DerivedA> b(new DerivedA);
Wrapper<DerivedB> c(new DerivedB);
Wrapper<DerivedC> d(new DerivedC);
a.doTest(hello);
b.doTest(hello);
c.doTest(hello);
d.doTest(hello);
return 0;
}

In your example you don't have a runtime polymorphism scheme (i.e., dynamic binding). What you have is an overloaded member function and in overload resolution the compiler correctly selects void world( Base *instance ).
In order to get what you want you should apply an inheritance scheme like the one below:
class Base {
public:
virtual ~Base() {}
virtual void world() const { std::cout << "Base" << std::endl; }
};
class DerivedA : public Base {
public:
virtual ~DerivedA() {}
void world() const { std::cout << "DerivedA" << std::endl; }
};
class DerivedB : public Base {
public:
virtual ~DerivedB() {}
void world() const { std::cout << "DerivedB" << std::endl; }
};
class DerivedC : public Base {
public:
virtual ~DerivedC() {}
using Base::world;
};
Live Demo
Edit:
In order to keep your code as intented in one place you could add to the above scheme the following altered version of the Test class:
class Test {
public:
void world( DerivedA *instance ) { instance->world(); }
void world( DerivedB *instance ) { instance->world(); }
void world( Base *instance ) { instance->world(); }
};
Live Demo
Unfortunately, overload resolution takes place at compile time whereas dynamic-dispatching takes place at run-time. Thus, if you intended for the compiler to deduce the underlying type from a Base pointer and then pick-up the right member function from Test class, this is not feasible.

Related

Size of derived class in virtual base class function

Consider the following code
class A {
int x, y;
public:
A(){}
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class B : public A {
int a, b, c;
public:
B(){}
};
int main() {
A obja;
B objb;
obja.PrintSize();
objb.PrintSize();
}
The intent of "PrintSize()" is to get the size of the current class where we are calling it from. What happens is that this-keyword refers to class A even though we are calling it from B. We don't want this since we need this function to be general for child classes.
We could obviously redefine the function verbatim to every class. The code would become harder to hande since there's so many unnesessary lines. Not to mention that re-writing the function to every class would defeat the purpose of deriving it in the first place.
Here's my temporary fix:
class A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class B : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class C : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
class D : public A {
public:
virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};
While the accepted answer may have solved the immediate problem, you suddenly have no common base class for B and C. They inherit from two unrelated classes, namely A<B> and A<C>.
An alternative is to create a common base that defines an interface (called Interface below) and to add the CRTP class template between the derived classes and the interface. This lets you keep pointers and references to Interface and call the virtual member functions using those.
Here's an example of storing pointers to the common base class in a vector:
#include <iostream>
#include <memory>
#include <vector>
struct Interface {
virtual ~Interface() = default;
virtual void PrintSize() const = 0;
virtual void do_stuff() const = 0;
};
template<typename T>
struct Printer : public Interface {
void PrintSize() const override {
std::cout << sizeof(T) << '\n';
}
};
class B : public Printer<B> {
int a{};
public:
void do_stuff() const override { std::cout << "B doing stuff\n"; }
};
class C : public Printer<C> {
int a{}, b{}, c{};
public:
void do_stuff() const override { std::cout << "C doing stuff\n"; }
};
int main() {
std::vector<std::unique_ptr<Interface>> objs;
objs.emplace_back(std::make_unique<B>());
objs.emplace_back(std::make_unique<C>());
for(auto& ptr : objs) {
ptr->do_stuff();
ptr->PrintSize();
}
}
Possible output:
B doing stuff
16
C doing stuff
24
You can use the CRTP idiom to do this.
https://eli.thegreenplace.net/2011/05/17/the-curiously-recurring-template-pattern-in-c
The idea is the parent class is a template, so you can have access to the type of the child class directly in it.
With that, you'll be able to remove all "PrintSize" from child class.
Example :
template <typename Derived>
class A {
int x, y;
public:
A() {}
void PrintSize() { cout << sizeof(Derived) << endl; }
};
class B : public A<B> {
int a, b, c;
public:
B() {}
};
class C : public A<C> {
public:
C() {}
};
int main() {
C objc;
B objb;
objc.PrintSize();
objb.PrintSize();
}
The output is :
8
20

How to get the name of a derived class from a vector of base classes

So I have a vector of base classes and a couple bugs in my code, which means that I need to know which derived class is calling the polymorphic method:
class Base {
virtual void render() {}
}
class Derived1 {
void render() override {/*do stuff*/}
}
class Derived2 {
void render() override {/*do stuff*/}
}
class Game {
std::vector<Base> baseVec;
void render() {
for(Base b: baseVec) {
b.render();
//std::cout << typeid(b).name() << std::endl; prints base class' name, and requires some logic to unmangle the actual name
//std::cout << std::type_index(typeid(b)).name() << std::endl; also prints base class' name
//std::cout << typeNames[std::type_index(typeid(b))] << std::endl; typeNames is an unordered_map<std::type_index, std::string> - still prints the base class' name, and the list has to be punched in by hand (bad)
}
}
}
Below code is modified for your requirement as per my understanding for your requirements:
class Base {
public:
virtual void render() = 0;
};
class Derived1: public Base {
void render() override { std::cout << "Derived1"<<std::endl; }
};
class Derived2: public Base {
void render() override { std::cout << "Derived2" << std::endl; }
};
int main()
{
std::vector<Base*> baseVec;
Derived1 d;
Derived2 d1;
baseVec.push_back(&d);
baseVec.push_back(&d1);
for (auto& b : baseVec)
{
b->render();
std::cout << typeid(*b).name() << std::endl;
}
return 0;
}
Output:
Derived1
class Derived1
Derived2
class Derived2
The typeid is solving your name by using=> typeid(*b).name().
typeid explained

Conditional call to base constructor

Currently, I have a based class with two different constructors:
class Base {
public:
Base(std::string filname){...}
Base(int a, int b) {...}
};
and a derived class of Base class. What I would like to do is to choose which constructor call inside the constructor of the derived class, but not in the initializer list. Something like this:
class Derived : public Base {
public:
Derived() {
if( /* exists("myFile") */ )
this->Base("myFile");
else
this->Base(1,2);
}
}
Is it possible to do that?, or because the base class is initialize before the derived class, the only way to call to the base constructor is in the initializer list?
Thanks
The choice of which base constructor is called happens before the body of the function and there's no way to change it at run time like that. However, you might be able to get close. If the base class also has a move constructor, or you could you add one, you could use that:
class Derived : public Base {
public:
Derived()
: Base{ exists("myFile") ? Base{"myFile"} : Base{1, 2} } {
}
}
This will call exists("myFile"); if that returns true, it will construct a temporary Base using the first constructor, and if it returns false it will construct a temporary Base using the second constructor. Either way, it will then construct the actual base subobject using this temporary.
You can simulate that by introducing a factory function:
class Base {
public:
Base(std::string filname);
Base(int a, int b);
};
class Derived : public Base {
Derived(std::string filname) : Base(filname) {}
Derived(int a, int b) : Base(a, b) {}
public:
static Derived create() {
if( /* exists("myFile") */ )
return Derived("myFile");
else
return Derived(1,2);
}
};
int main(){
auto d = Derived::create();
}
Alternatively, if derivation from Base is not required, an instance of Base can be held as a member (std::unique_ptr or std::aligned_storage) that you can initialise however you please.
Based on #DanielH comment in his answer I have developed an alternative solution which also works with abstract base classes in C++11:
#include <iostream>
struct Base {
Base(int x) {
std::cout << "Base x = " << x << std::endl;
}
Base() {
std::cout << "Base default" << std::endl;
}
virtual void foo() = 0;
};
struct Derived : Base {
struct TagA {};
struct TagB {};
Derived(bool condition)
: Derived(condition ? Derived{TagA()} : Derived{TagB()})
{}
void foo() override {}
private:
Derived(TagA dummy)
: Base(42)
{
std::cout << "Derived A dummy" << std::endl;
}
Derived(TagB dummy)
{
std::cout << "Derived B dummy" << std::endl;
}
};
int main() {
std::cout << "Construct Derived with false" << std::endl;
Derived x(false);
std::cout << "Construct Derived with true" << std::endl;
Derived y(true);
}

Call virtual function after derived class object construction

Here is some sample code:
#include <iostream>
class A {
public:
virtual void foo() {
std::cout << "base" << std::endl;
}
A() {
foo();
}
};
class B : public A {
int a;
public:
void foo() {
std::cout << "derived" << std::endl;
}
B(int a) :
a(a) {}
};
int main() {
B o(1);
return 0;
}
I want foo() to get called every time some A derived object is constructed. I do not want to call foo() explicitly in every derived class constructor.
Is there a way to do this in some elegant way?
There is no way you can call an overridden foo() from a base class constructor, no matter what you do. When the base class constructor is called, the derived class object has not been constructed yet, so you cannot call any of its methods or access any of its members. This is true for virtual functions and regular functions as well. In a base class constructor, the this pointer is pointing at the base class, not the derived class.
A potential workaround is to delegate construction to a separate function that clients will have to call instead. Then have that function call foo after construction:
class A {
public:
virtual void foo() {
std::cout << "base" << std::endl;
}
template<typename T, typename ... Args>
static T construct(Args ... args)
{
T newT{ args... };
newT.foo();
return std::move(newT);
}
protected:
A() {
//Construct A
}
};
class B : public A {
int a;
public:
void foo() {
std::cout << "derived" << std::endl;
}
B(int a) :
a(a) {}
};
int main()
{
B o = A::construct<B>(1);
A a = A::construct<A>();
return 0;
}

overriden virtual function is not getting called

a more exact version of the code is:
class SomeParam;
class IBase
{
public:
virtual void Func(SomeParam* param = NULL)
{
cout << "Base func";
}
};
class DerivedA : public IBase
{
public:
void Func()
{
//do some custom stuff
cout << "DerivedA func";
IBase::Func();
}
};
class DerivedB : public IBase
{
public:
void Func()
{
//do some custom stuff
cout << "DerivedB func";
IBase::Func();
}
};
//at somewhere else
void FuncCaller(IBase *instance1, IBase *instance2)
{
IBase *i1 = instance1;
IBase *i2 = instance2;
i1->Func();
i2->Func();
}
DerivedA *a = new DerivedA;
DerivedB *b = new DerivedB;
FuncCaller(a,b);
This gives me:
"Base func"
"Base func"
It looks like you have provided a simplified version of your code to make it more readable, but you have oversimplified inadvertently.
The most likely reasons for your behaviour are:
Slicing in FuncCaller() (see quamrana's answer for the details)
Wrong overriding, such as making the derived class function const, while the base class function is not const
EDIT: After reading the edited question, it is clearly the second reason. You are not overriding the base class function, but hiding it in the derived classes with a new definition. You need to keep exactly the same signature (covariance does not apply here, since the function returns void) in the derived classes. In code, you need to do either:
class SomeParam;
class IBase
{
public:
virtual void Func(SomeParam* param = NULL)
{
cout << "Base func";
}
};
class DerivedA : public IBase
{
public:
void Func(SomeParam* param = NULL)
{
//do some custom stuff
cout << "DerivedA func";
IBase::Func();
}
};
class DerivedB : public IBase
{
public:
void Func(SomeParam* param = NULL)
{
//do some custom stuff
cout << "DerivedB func";
IBase::Func();
}
};
//at somewhere else
void FuncCaller(IBase *instance1, IBase *instance2)
{
IBase *i1 = instance1;
IBase *i2 = instance2;
i1->Func();
i2->Func();
}
DerivedA *a = new DerivedA;
DerivedB *b = new DerivedB;
FuncCaller(a,b);
or
class SomeParam;
class IBase
{
public:
virtual void Func()
{
cout << "Base func";
}
};
class DerivedA : public IBase
{
public:
void Func()
{
//do some custom stuff
cout << "DerivedA func";
IBase::Func();
}
};
class DerivedB : public IBase
{
public:
void Func()
{
//do some custom stuff
cout << "DerivedB func";
IBase::Func();
}
};
//at somewhere else
void FuncCaller(IBase *instance1, IBase *instance2)
{
IBase *i1 = instance1;
IBase *i2 = instance2;
i1->Func();
i2->Func();
}
DerivedA *a = new DerivedA;
DerivedB *b = new DerivedB;
FuncCaller(a,b);
I found the reason:
The overriden virtual functions also must have a default parameter like Base's.like:
class DerivedB : public IBase
{
public:
void Func(SomeParam* param=NULL)
{
//do some custom stuff
cout << "DerivedB func";
IBase::Func();
}
};
Thanks for the answers guys.
Your virtual function is not overridden.
Your supposedly "virtual" methods in the derived classes have different signatures. The method in the base class has one parameter, while the methods in the derived classes have no parameters. Because of this, the methods in the derived classes are completely unrelated to the base class method. They don't override the base class method. This is why the base class method is always called.
I've tried a copy of the code you posted on VS2008 and it works fine.
I can only suggest that your actual code is more like:
void FuncCaller(IBase instance)
{
instance.Func();
}
void Funcs()
{
DerivedA *a = new DerivedA;
DerivedB *b = new DerivedB;
FuncCaller(*a);
FuncCaller(*b);
}
where FuncCaller slices the base part off the derived instances.