How can we pass a function pointer as an argument? For example, the function pointer myFunPtr is an argument when calling class A and I need this pointer to point to function funcB in class B
#include <iostream>
typedef void(*myFunPtr)(void);
class A {
public:
A(myFunPtr ptr);
virtual ~A();
myFunPtr funptr;
};
A::A(myFunPtr ptr){
std::cout << "Constructor A \n";
funptr = ptr;
}
A::~A(){}
///////////////
class B {
public:
B();
virtual ~B();
void funcB();
};
B::B(){
std::cout << "Constructor B \n";
A *objA = new A(funcB);
}
B::~B(){}
void B::funcB(){
std::cout << " call B::funcB \n";
}
///////////////
int main(){
B *objB = new B();
delete objB;
return 0;
}
This is a function pointer type to a free function (not a class member function):
typedef void(*myFunPtr)(void);
This is a B member function pointer type:
typedef void(B::*myFunPtr)(void);
Demo
Here's another Demo that will call a member function in a B. To do that, a pointer to a B and a pointer to a B member function is stored in A.
Related
#include <iostream>
using namespace std;
class A {
public:
virtual void f() = 0;
};
class B : public A {
public:
void f() {cout << "hi" << endl;}
void g() { cout << "bye" << endl; }
};
int main() {
B b;
A &a = b;
a.f(); // prints "hi"
a.g(); // compile error no member g()
return 0;
}
why does a.g() give compile error while a.f() calls B's f()?
At A &a = b; does the compiler somehow set a boundary of where a's aliasing memory ends?
You are attempting to call g() from an instance of A. A does not have an implementation of g(), so it cannot be called through an A object. The fact that a is a reference to a B does not give a access to any functions that A does not know about.
B, on the other hand is-a A, and defines an implementation of the virtual function f(), so the reference a invokes the correct function.
Look at this excerpt of a program.
I see that cout << obj->foo(); call is not polymorphic. Actually, it is obvious, because it has no virtual specificator.
But I am confused with cout << ((B*)obj)->foo(); Why the program does not use the B's definition of virtual function and will call the third version of foo()?
#include <iostream>
using namespace std;
class A{
public:
int foo(){ return 1; }
};
class B: public A{
public:
virtual int foo(){ return 2; }
};
class C: public B{
public:
int foo(){ return 3; }
};
int main() {
A* obj = new C;
cout << obj->foo();
cout << ((B*)obj)->foo();
cout << ((C*)obj)->foo();
return 0;
}
A::foo() is not virtual. Calling foo() via an A* pointer (or A& reference) will call A::foo() directly without any polymorphic dispatch.
B::foo() is virtual. Calling foo() via a B* pointer (or B& reference) will dispatch the call to the most derived implementation of foo() that exists in the object that the B* (or B&) refers to.
C derives from B, and C::foo() overrides B::foo(), and obj points to a C object, which is why C::foo() gets called by polymorphic dispatch when foo() is called via a B* or C* pointer (or a B& or C& reference).
Because ((B*)obj)->foo(); behaves by design like B* b = (B*)obj; b->foo() and calls C::foo. You may call the base's method explicitly like ((B*)obj)->B::foo();.
#include <iostream>
using namespace std;
class A{
public:
int foo(){ return 1; }
};
class B: public A{
public:
virtual int foo(){ return 2; }
};
class C: public B{
public:
int foo() override { return 3; }
};
int main() {
A* obj = new C;
cout << obj->foo();
cout << ((B*)obj)->B::foo();
cout << ((C*)obj)->foo();
return 0;
}
Output: 123
Member function foo is virtual from class B downwards, i.e. also in C, even if it is not marked virtual or override there.
Thus, call ((B*)obj)->foo() is a virtual call, actually resulting in calling C::foo.
Why is the output of this program "CLASS A"? Isn't this determined to be of type B? Doesn't it mean that this->g() should call the B class's version of g?
#include <iostream>
using namespace std;
class A {
private:
void g() {
cout << "CLASS A" << endl;
}
public:
virtual void f() {
g();
}
};
class B : public A {
public:
void g() {
cout << "CLASS B" << endl;
}
};
int main() {
A* a = new B();
a->f();
}
Isn't this determined to be of type B?
No. B may be the dynamic type, but the static type of *this is A within all its member functions.
The member function g is not virtual, so therefore a call to it uses static binding. In static binding, the dynamic type of the object is irrelevant - only the static type matters. A call to the non-virutal g within a member function of A should be a call to A::g.
#include <iostream>
using namespace std;
class A {
};
typedef void (A::*funA)(int);
class B : public A {
public:
void m(int) {std::cout << "mm" << std::endl; }
void n(int) { std::cout << "nn"<<std::endl; }
};
typedef void (B::*funB)(int);
class C : public B {
public:
void g(int) {std::cout << "gg" << std::endl; }
void h(int) { std::cout << "hh"<<std::endl; }
};
typedef void (C::*funC)(int);
int main() {
funB f = static_cast<funB>(&C::m);
A* pa = new A;
(pa->*(static_cast<funA>(f)))(2);
return 0;
}
gcc compile and output "mm".
But why can this work? Class A in fact don't define any function.
It seems the class can use its base class or derived class function by this way, even though it doesn't define them.
Since A doesn't contain the member that f refers to, the behaviour is undefined.
The probable reason why it works anyway is that the function B::m doesn't touch the this pointer, so it doesn't "notice" when it's called on an object of the wrong type. Also, A and B are not polymorphic, so dereferencing the pointer-to-member and calling doesn't require examining any vptr.
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.