Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::bind and non-virtual call to base class method

Tags:

c++

I want to use std::bind and do non-virtual call to base class function eg: derived_obj.BaseClass::foo()


Example:

Let's say I have base class A and derived class B. A has a virtual function foo() which is overridden by B.

class A
{
   public:
     virtual void foo() { std::cout << "Hello from A::foo()!";}
}

class B : public A
{
   public:
     void foo() overide { std::cout << "Hello from B::foo()!";}
}

If I want to call A::foo() from object of class B I do non-virtual call:

B b_obj;
b_obj.A::foo(); // prints "Hello from A::foo()!"


Now I want to use std::bind and do non-virtual call to A::foo() from b_obj, how do I do this?

I've already tried by casting b_obj to A and use address of &A::foo(), but had no luck.

auto f = std::bind(&A::foo, static_cast<A*>(&b_obj));
f(); // prints "Hello from B::foo()!" but it should print "Hello from A::foo()!"
like image 744
Allin Avatar asked Jul 21 '16 09:07

Allin


People also ask

Can you override non-virtual methods?

You cannot override a non-virtual or static method. The overridden base method must be virtual , abstract , or override . An override declaration cannot change the accessibility of the virtual method. Both the override method and the virtual method must have the same access level modifier.

Can we override non-virtual method in CPP?

It is allowed and it's not a problem - and if you call the method directly as you have done it will be called fine. But, being non-virtual, C++ method lookup mechanisms that allow for polymorphism won't be used.

How do you call a virtual method of base class in C++?

When you want to call a specific base class's version of a virtual function, just qualify it with the name of the class you are after, as I did in Example 8-16: p->Base::foo(); This will call the version of foo defined for Base , and not the one defined for whatever subclass of Base p points to.

Can a virtual function call a non-virtual function?

So polymorphic behaviour works even when a virtual function is called inside a non-virtual function. The output can be guessed from the fact that the function to be called is decided at run-time using the vptr and vtable.

How to call a base class virtual function from a derived class?

Calling a base class virtual function from a derived class September 8, 2016martin You can call a base class version of a virtual function from a derived class by prefixing its name with the name of the base class. For example, if you have the following base class:

How to call a method within a derived class in C++?

You can call its version of method()within a derived class like this: class Derived : public Base { virtual void method() { Base::method(); std::cout << "Derived::method()" << " "; } virtual ~Derived() { } }; Example program:

Can you override a virtual method in a derived class?

When the method is declared as virtual in a base class, and the same definition exists in a derived class, there is no need for override, but a different definition will only work if the method is overridden in the derived class. By default, methods are non-virtual, and they cannot be overridden.

What is a virtual base class in Java?

Virtual base classes offer a way to save space and avoid ambiguities in class hierarchies that use multiple inheritances. When a base class is specified as a virtual base, it can act as an indirect base more than once without duplication of its data members.


2 Answers

You have two options here. You should either do the non-virtual call in a lambda or you go the trusty old way of slicing the object (which is a copy) you want to pass to std::bind.

// Base method
B b_obj; b_obj.A::foo(); // prints "Hello from A::foo()!"

// First method
auto k = [](auto b){ b.A::foo(); };
k(b_obj);

// Second method
auto f = std::bind(&A::foo, *static_cast<A*>(&b_obj));
f(); 

This all prints:

Hello from A::foo()!
Hello from A::foo()!
Hello from A::foo()!

The Second method works (slices) since std::bind copies its arguments. You should really prefer a lambda.

like image 172
WhiZTiM Avatar answered Nov 15 '22 10:11

WhiZTiM


You could wrap the call inside a lambda:

B b_obj;
auto f = std::bind([&b_obj]() { b_obj.A::foo(); } );

But this makes little sense unless you can only use std::bind somewhere (for example because of std::is_bind_expression), as you pass the object parameter to the lambda's capture, not to bind.

Otherwise just using a lambda or std::function without bind should be cleaner.

like image 31
Dutow Avatar answered Nov 15 '22 10:11

Dutow