i hope this makes sense for you, i get confused. let me know if there is a simpler way:
double A::a(double(b::*bb)())
{
b.init();
return (b->*bb)();
}
void A::run();
{
cout<< a(b.b1);
cout<< a(b.b2);
}
class A
{
B b;
void run();
double a(double(b::*bb)());
};
class B
{
void init();
double b1();
double b2();
};
It doesn't make sense. This makes sense though:
class B // <- class B definition comes first
{
void init();
double b1();
double b2();
};
class A
{
B b;
void run();
double a(double(B::*bb)()); // <- B instead of b
};
double A::a(double(B::*bb)()) // <- B instead of b
{
b.init();
return (b->*bb)();
}
void A::run() // <- you can't put semicolon here
{
cout<< a(&B::b1); // <- you want to pass the address of a member.
cout<< a(&B::b2); // <- you want to pass the address of a member.
}
Now it makes more sense to me.
This:
double a(double(b::*bb)());
Should be:
double a(double(B::*bb)());
That is, bb is to be declared as a pointer to member function in the class B, not in the object b (which is an instance, not a type itself, therefore cannot be part of a type).
Related
I have a nested class B inside class A. I need to pass a custom function with one integer argument and return type of void at runtime to class B.
This is how I tried to do it. First I passed the function through the constructor of A. And then to pass it to B, I tried to use pointer to member function. However I can't figure out how to call function foo() inside doStuff().
class A {
void(*f)(int);
A(void(*f)(int)) : f(f) {};
class B {
void(*A::*foo)(int) = &A::f;
void doStuff() {
var = 10;
*foo(var); //Doesn't work
}
};
};
void testFunction(int a) {
//do something
}
A a(testFunction);
What is the correct way to call it? And does this solution make sense as the whole?
Edit: Possible alternative solution:
class A {
A(void(*f)(int)) {
b = B(f);
}
class B {
void(*f)(int);
B() {}
B(void(*f)(int)) : f(f) {}
void doStuff() {
var = 10;
f(10);
}
};
B b;
};
Note that in order to call a pointer-to-function member of A you need an object of type A to call it on. In the example below, the reference to an A object was passed as an argument to B::doStuff.
#include <iostream>
class A
{
public:
void (*f)(int);
A(void (*f)(int)) : f(f) { }
class B {
public:
void (*A::*foo)(int) = &A::f;
void doStuff(A &a) {
(a.*foo)(10);
}
};
};
void testFunction(int a) {
std::cout << "inside testFunction(" << a << ")" << std::endl;
}
int main()
{
A a(testFunction);
A::B b;
b.doStuff(a);
}
Example output: inside testFunction(10).
I understand how C++ solves the diamond problem in multiple inheritance by using virtual inheritance. Suppose the following situation:
class A {
int num;
public:
int get_num() const { return num; }
};
class B : public A {
void foob() { int x = get_num(); }
};
class C : public A {
void fooc() { int x = get_num(); }
};
class D : public B, public C {
void food() { int x = get_num(); }
};
The get_num() call is ambiguous inside food(). I know I can fix it either by calling A::get_num() or by virtual inheritance using virtual public A. But I can see a third approach:
class A {
int num;
public:
int get_num() const { return num; }
};
class B : public A {
void foob() { int x = get_num(); }
};
class C { // won't inherit from A anymore
const A& base; // instead keeps a reference to A
void fooc() { int x = base.get_num(); }
public:
explicit C(const A* b) : base(*b) { } // receive reference to A
};
class D : public B, public C {
void food() { int x = get_num(); }
public:
D() : C(this) { } // pass "this" pointer
};
The external code doesn't need to consider C as an A.
Considering it has no impacts on my particular class hierarchy design, are there any advantages of the third approach over the virtual inheritance way? Or, in terms of cost, it ends up being the same thing?
Congratulations ! You've just re-invented the principle of composition over inheritance !
If this works with your design, it means that C was in fact not a kind of A, and there was no real justification to use inheritance in first place.
But don't forget the rule of 5 ! While your approach should work in principle, you have a nasty bug here : with your current code, if you copy a D object, its clone uses the wrong reference to the base (it doesn't refer to it's own base, which can lead to very nasty bugs...
Demo of the hidden problem
Let's make A::get_num() a little bit more wordy, so that it tells us about the address of the object that invokes it:
int get_num() const {
cout << "get_num for " << (void*)this <<endl;
return num;
}
Let's add a member function to C, for the purpose of the demo:
void show_oops() { fooc(); }
And same for D:
void show() { food(); }
Now we can experiment the problem by running this small snippet:
int main() {
D d;
cout<<"d is "<<(void*)&d<<endl;
d.show();
d.show_oops();
D d2=d;
cout<<"d2 is "<<(void*)&d2<<endl;
d2.show();
d2.show_oops();
}
Here an online demo. You will notice that d2 does produce inconsistent results, like here:
d is 0x7fffe0fd11a0
get_num for 0x7fffe0fd11a0
get_num for 0x7fffe0fd11a0
d2 is 0x7fffe0fd11b0
get_num for 0x7fffe0fd11b0
get_num for 0x7fffe0fd11a0 <<< OUCH !! refers to the A element in d !!
Not only do you refer to the wrong object, but if the d object would decease, you would have a dangling reference, so UB.
Please check the following code. Why it is wrong and how to fix? Thank you.
class A
{
public:
class B
{
public:
B(int(*cf)())
{
f = cf;
}
int (*f)();
};
B *b;
A()
{
b = new B(this->a);
}
int a()
{
}
};
int main()
{
A a;
}
compilation error:
If you absolutely need to call a function by pointer you will need to use a pointer to member function instead of a pointer to function. A pointer to member function has a different declaration syntax that includes the class type the function belongs to. In your case the parameter declaration would look like int (A::*cp)(). You will also need to change the declaration of the f member variable to int (A::*f)().
In order to call a pointer to member function you need to have a pointer to an object of the type the function belongs to. You also need to use one of the pointer to member operators; ->* or .*
void call(A* c, int (A::*f)())
{
(c->*f)(); // call member function through pointer
}
The extra set of parenthesis is required due to the order of precedence of operators.
The following code includes the changes necessary for you to use pointer to member functions.
class A
{
public:
class B
{
public:
// Take a pointer to member function.
B(int(A::*cf)())
{
f = cf;
}
void call(A* c)
{
(c->*f)();
}
int (A::*f)(); // pointer to member function
};
B *b;
A()
{
b = new B(&A::a);
}
int a()
{
return 0;
}
};
int main()
{
A a;
a.b->call(&a);
}
I also recommend that you consider using std::function and std::bind (or their Boost equivalents if you do not have a C++11 compiler).
Do not use function pointers in the first place when using C++.
There is an easier and more elagant solution - an interface.
i.e.
class Interface {
public:
virtual int CallMe() = 0;
};
class B : public Interface { int CallMe() { return 5; };
class A : public Interface {
private:
Interface *m_i = 0;
public:
A(Interface *i) : m_i(i) { }
A() : m_i(this) { };
void DoIt() { cout << m_i->CallMe() << endl; }
int CallMe() { return 8; }
};
int main() {
A a(new B); // Coult be any object that implements Interface (as yes it is a memory leak
A aa();
a.DoIt(); // Will print 5
aa.DoIt(); // WIll print 8
return 0;
}
if I declare:
class Avoidance : public Schema<std_msgs::String,prog1::Command>{
and I try to
void*(Schema<std_msgs::String,prog1::Command>::*pt)();
pt=&Avoidance::frontBusy;
compiler report me
error: cannot convert ‘void* (Avoidance::*)()’
to
‘void* (Schema<std_msgs::String_<std::allocator<void> >, prog1::Command_<std::allocator<void> > >::*)()’ in assignment
why? Avoidance inherits from
Schema<std_msgs::String,prog1::Command>
then Avoidance IS Schema<.....>
That's not how member function pointers work. If frontBusy is a base function, you need to type the pointer appropriately. The dispatch will still work as expected, though!
Here's a basic example:
struct A { virtual void f() = 0; };
struct B : A { virtual void f() { } };
void dispatch(void (A::*pf)(), A & a)
{ // ^^^^^
(a.*pf)();
}
int main()
{
B x;
dispatch(&A::f, x); // calls x.B::f()
} // ^^^^^
So, in your case you want:
void (Schema<std_msgs::String,prog1::Command>::*p)()
= &Schema<std_msgs::String,prog1::Command>::frontBusy;
Getting rid of templates to simplify, suppose you have
class B {
public:
void f();
};
class D : public B {
public:
void g();
};
It might seem a little backwards at first, but you can cast void (B::*)() to void (D::*)(), but you cannot cast void (D::*)() to void (B::*)(). This makes sense when you think about how they would later be used.
void test() {
void (D::*p)() = &B::f; // OK!
void (B::*q)() = &D::g; // ERROR!
B b;
D d;
(d.*p)(); // Calls B::f on `d`. Okay, `B::f` is an inherited member.
(b.*q)(); // Calls D::g on `b`?? But that's not a member of `b` at all!
}
I want to call a member function of another class on an object, but I cant seem to figure out how this works. As example code on how it should work:
Class A {
void somefunction(int x);
}
Class B : A {
void someotherfunction(int x);
}
Class C {
void x() {
callY(&ofthefunction);
} //here you call the function, you dont have an object yet, and you don't know the argument yet, this will be found in function callY
void Y(*thefunction) {
find int x;
if(something)
A a = find a;
a->thefunction(x);
else
B b = find b;
b->thefunction(x);
}
}
I hope this makes sence, It is also possible to split this in 2 methods, Y1 and Y2, but seeing as 90% of the code is the same (finding things in a XML file), only the object and argument where to save it is different, i'd like to do this
You can use something known as a virtual function. By the way, your syntax is hideous, it's class not Class, you need braces for your conditionals, and a judicious application of public, some extra semicolons, etc. It would be appreciated if you would go near a compiler before coming here, y'know.
class A {
public:
virtual void somefunction(int x);
};
class B : public A {
public:
virtual void somefunction(int x);
};
void func(A& a) {
int x = 0;
// Do something to find x
a.somefunction(x);
// calls A::somefunction if this refers to an A
// or B::somefunction if it's a B
}
int main() {
A a;
func(a); // calls A::somefunction
B b;
func(b); // calls B::somefunction
}
What you want to do can be done, although I woudn't solve it this way:
class A {
public:
virtual int doit(int x) { return x+1; }
};
class B : public A {
public:
int doit2(int x) { return x*3; }
int doit(int x) { return x*2; }
};
int foo(int (A::*func)(int), int x, bool usea) {
if (usea) {
A a;
return (a.*func)(x);
} else {
B b;
return (b.*func)(x);
}
}
int main() {
int (A::*bla)(int) = &A::doit;
foo(bla, 3, true);
foo(bla, 3, false);
}
However, for this to work, the following has to be satisfied:
You must use function pointers of the base class (e.g. int (A::*bla)(int)), otherwise you won't be able to call it on that base class (e.g. int (B::*bla)(int) can only be used on B instances, not on A instances, even if the method is already defined in A).
The methods must have the same names as in the base class
To use overriding (e.g. different impl in derived class), you have to use virtual functions.
But I would rather rethink your design...
No, that won't work at all. A pointer to a member of A will always point to that function, even when it's called on B because B inherits from A.
You need to use virtual functions. I see DeadMG has beaten me to it.