我正在做一个项目,我需要涉及到函数指针,更具体地说,是指向成员函数的函数指针。我几乎阅读了所有相关的问题,但是没有一个是描述我的具体问题的。所以,我将试着用一个简单的例子来描述我的问题。
让我们假设我有三个不同的头文件和不同的类,如下所示:
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
}
因此,结构体Foo1
的成员变量之一是指向Foo2
的成员函数print_foo2
的函数指针。出于这个原因,我创建了对象foo1
的实例,并为它分配了一个指向print_foo2
的指针。类Foo3
继承自类Foo2
我注意到,正如我所想,它可能是解决问题的有用信息。但是,我无法获得指向函数的指针,因为Foo2
在结构体Foo1
中无法识别。即使在foo1.h
中包含foo2.h
也无济于事。如果我没有弄错的话,这是因为Foo1
在构造过程中需要Foo2
作为其成员变量,但以同样的方式Foo2
需要构造Foo1
。因此,这会导致死锁。
这是问题的原因吗?如果是,我该如何解决?
既然Foo2
和Foo3
都需要Foo1
的定义,那么它们都应该是#include "foo1.h"
。如果没有Foo1
的定义,编译器将无法计算Foo2
和Foo3
的大小。
另一方面,Foo1
不需要Foo2
的定义,因此可以转发声明Foo2
来解决死锁。无论如何定义Foo2
,它保留的指针(fp
)将具有相同的大小,这就是为什么前向声明足够了。
评论内联:
// 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};
};
注意:在代码中,Foo2
和Foo3
都有一个Foo1
成员变量。这意味着Foo3
总共有2个。如果您在Foo3
中只有一个一个Foo1
,而希望Foo3
在继承的Foo2
中初始化Foo1
,则可以从Foo3
中删除Foo1
成员并初始化基类(Foo2
),如下所示:
class Foo3 : public Foo2{
public:
Foo3() : Foo2{1, 3.141, &Foo2::print_foo2} {}
};