I was working on a project where I needed to get involved with function pointers, more specifically function pointer to member functions. I have read almost all the related questions, however none of them describing my specific problem. So, I will try to describe my problem by a simple example.
Let's assume that I have three different header files with different classes, like given below:
foo1.h
struct Foo1{
int a1;
double b1;
void (Foo2::*fp)(const double);
}
foo2.h
#include "foo1.h"
class Foo2{
public:
void print_foo2(const double p){
cout << "From Foo2: " << p << endl;
}
Foo1 foo1;
}
foo3.h
class Foo3 : public Foo2{
Foo1 foo1;
foo1.fp = &Foo2::print_foo2; // cannot do that
}
So, one of the member variables of struct Foo1
is a function pointer to the member function of Foo2
, namely print_foo2
. For that reason, I create instance of object foo1
and assign it a pointer to the print_foo2
. Class Foo3
inherits from class Foo2
.
I noted that, as I thought, may be it can be useful information for solution of the problem. However, I cannot get that pointer to the function as Foo2
is not recognized inside struct Foo1
. Even including foo2.h
in foo1.h
doesn't help. If I am not mistaken, this is because Foo1
requires Foo2
for its member variable during construction, but in the same way Foo2
requires Foo1
to be constructed. So, this creates a deadlock.
Is it the cause of the problem? If yes, how can I solve it?
CodePudding user response:
Since both Foo2
and Foo3
need the definition of Foo1
, they should both #include "foo1.h"
. Without the definition of Foo1
the compiler will not be able to calculate the size of neither Foo2
nor Foo3
.
Foo1
on the other hand does not need the definition of Foo2
and can therefore forward declare Foo2
to resolve the deadlock. The pointer (fp
) it keeps will have the same size no matter how Foo2
is defined which is why a forward declaration is enough.
Comments inline:
// foo1.h
#pragma once
class Foo2; // forward declaration
struct Foo1{
int a1;
double b1;
void (Foo2::*fp)(const double);
};
// foo3.h
#pragma once
#include "foo2.h"
#include "foo1.h" // not strictly needed since `foo2.h` includes it
class Foo3 : public Foo2{
// proper initalization:
Foo1 foo1{1, 3.141, &Foo2::print_foo2};
};
Note: In your code, both Foo2
and Foo3
has a Foo1
member variable. That means that Foo3
has 2 in total. If you only one one Foo1
in Foo3
and instead want Foo3
to initialize the Foo1
in the inherited Foo2
, you can remove the Foo1
member from Foo3
and initialize the base class (Foo2
) like so:
class Foo3 : public Foo2{
public:
Foo3() : Foo2{1, 3.141, &Foo2::print_foo2} {}
};