[英]Can a member function pointer refer to a method of one of several different classes?
This is what I have:这就是我所拥有的:
class Foo;
class Bar;
class FooBar
{
public:
FooBar( Foo &f, void ( Foo::* signal )( FooBar* ) )
: m_Foo(&f)
, fp_Foo(signal) {};
FooBar( Bar &b, void ( Bar::* signal )( FooBar* ) )
: m_Bar(&b)
, fp_Bar(signal) {};
protected:
void ( Foo::*fp_Foo )( FooBar* );
void ( Bar::*fp_Bar )( FooBar* );
private:
Foo *m_Foo{nullptr};
Bar *m_Bar{nullptr};
};
This is what I want:这就是我要的:
class Foo;
class Bar;
class FooBar
{
public:
FooBar( Foo &f, void ( Foo::* signal )( FooBar* ) )
: m_Foo(&f)
, fp(signal) {};
FooBar( Bar &b, void ( Bar::* signal )( FooBar* ) )
: m_Bar(&b)
, fp(signal) {};
protected:
void ( <???>::*fp )( FooBar* ); // Deduplicated
private:
Foo *m_Foo{nullptr};
Bar *m_Bar{nullptr};
};
I want only one set of member function pointers, that can stand in for both Foo
and Bar
.我只想要一组成员 function 指针,它们可以代表
Foo
和Bar
。
Is this possible without the use of a template?如果不使用模板,这可能吗?
Thanks.谢谢。
To me it seems, that you have a XY problem.在我看来,你有一个 XY 问题。 That is why I will concentrate on what you actually want to achieve, ie:
这就是为什么我将专注于您真正想要实现的目标,即:
I want to add some signals to a QList based class for insertions, changes, and removals.
我想向基于 QList 的类添加一些信号以进行插入、更改和删除。 The Q_OBJECT macro however will not work on this:
但是 Q_OBJECT 宏不适用于此:
class CardList : public QList<Card*>
QList
is not a QObject
. QList
不是QObject
。
Subclass QObject
and compose the subclass with a list.子类
QObject
并用列表组合子类。
Here is a simple example I have written for you to demonstrate the proposed solution:这是我为您编写的一个简单示例,用于演示建议的解决方案:
#include <QObject>
class Card;
class CardList : public QObject // inheritance
{
Q_OBJECT
public:
explicit CardList(QObject *parent = nullptr);
void addCard(Card *); // emit cardAdded here
int cardCount() const;
Card *card(int pos);
bool removeCard(int pos); // emit cardRemoved here
private:
QList<Card *> m_cards; // composition
signals:
void cardAdded(int pos);
void cardRemoved(int pos);
};
Now you can have:现在你可以拥有:
class Game : public QObject
{
...
private:
CardList *m_cards;
...
}
class Player : public QObject
{
...
private:
CardList *m_cards;
...
}
That all being said, maybe a model would suite the needs of your application better.话虽如此,也许模型会更好地满足您的应用程序的需求。
One option is to use a std::function
in which you store a lambda that calls what you want to call:一种选择是使用
std::function
存储 lambda 调用你想要调用的内容:
#include <functional>
class FooBar {
public:
FooBar(Foo& f, void (Foo::*signal)(FooBar*)) : m_f{[&]{ (f.*signal)(this); }}
{};
FooBar(Bar& b, void (Bar::*signal)(FooBar*)) : m_f{[&]{ (b.*signal)(this); }}
{};
void call() {
m_f();
}
private:
std::function<void()> m_f;
};
If you prefer to have the instance and member function pointer available, you can use a union
to accomplish this.如果您希望实例和成员 function 指针可用,则可以使用
union
来完成此操作。 Since you are using C++17, you should however prefer using a std::variant
.由于您使用的是 C++17,因此您应该更喜欢使用
std::variant
。
Here's an example of how that could look:这是一个看起来如何的示例:
#include <utility>
#include <variant>
class FooBar {
public:
FooBar(Foo& f, void (Foo::*signal)(FooBar*)) : m_fp{std::pair{&f, signal}} {};
FooBar(Bar& b, void (Bar::*signal)(FooBar*)) : m_fp{std::pair{&b, signal}} {};
void call() {
std::visit([this](auto&& fb){
auto&[i, m] = fb;
(i->*m)(this);
}, m_fp);
}
private:
// store both the instance pointer and member pointer in pairs:
std::variant<std::pair<Foo*, void(Foo::*)(FooBar*)>,
std::pair<Bar*, void(Bar::*)(FooBar*)>> m_fp;
};
If you for some reason do not want to use a std::variant
and std::pair
s, just create a similar union
:如果您出于某种原因不想使用
std::variant
和std::pair
,只需创建一个类似的union
:
struct foopair {
Foo* i;
void (Foo::*m)(FooBar*);
};
struct barpair {
Bar* i;
void (Bar::*m)(FooBar*);
};
union foobaru {
foobaru(Foo& f, void (Foo::*signal)(FooBar*)) : fp{&f, signal} {};
foobaru(Bar& b, void (Bar::*signal)(FooBar*)) : bp{&b, signal} {};
foopair fp;
barpair bp;
};
class FooBar {
public:
FooBar(Foo& f, void (Foo::*signal)(FooBar*)) :
has_foo{true}, m_fb{f, signal} {};
FooBar(Bar& b, void (Bar::*signal)(FooBar*)) :
has_foo{false}, m_fb{b, signal} {};
void call() {
if(has_foo) {
auto&[i, m] = m_fb.fp;
(i->*m)(this);
} else {
auto&[i, m] = m_fb.bp;
(i->*m)(this);
}
}
private:
bool has_foo;
foobaru m_fb;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.