【问题标题】:Is there a way to refer to methods of a class within a collection?有没有办法在集合中引用类的方法?
【发布时间】:2019-12-12 13:55:35
【问题描述】:

我个人希望 Qt 使用这个,所以如果代码关闭,请随时修复它。

我想要的是创建一个可以引用类成员的集合。我尝试了函数指针,但我得到错误我不能使用非静态成员或类似的东西。我试过&ClassName::memberName,但这给了我一些关于它必须是常数或其他东西的错误。

我不确定要提供什么样的代码,因为我试图询问在 c++ 中是否有可能。


上下文

因为人们可能会问我为什么要这样做,所以我计划在我的软件中为各种“工具”提供一长串方法。每个工具都与 4 个鼠标事件相关联:1 个用于移动、释放、按下、双击。

我想保持效率,所以我希望做类似的事情

enum class MouseAction { MOVE=-1, RELEASE, PRESS, DOUBLECLICK }
void mousePressed(MouseEvent *e) {mouseActionMethod[toolName][MouseAction::PRESS](e);}

为此,我需要一个 map<Action, map<MouseAction, void*>> 类型的集合,我将在其中将类成员作为函数指针插入到 void* 中。但是,这样做会导致错误。

如前所述,尝试以几种方式执行此操作,结果令人困惑。如果我在浪费任何额外的努力之前发现这是不可能的,那就更好了。

我还将void* 替换为(ClassName*) 以尝试&ClassName::methodName,这是基于我在堆栈溢出中发现的另一个问题 - 该解决方案似乎不适用于我。

【问题讨论】:

  • 一个非静态成员函数对类的一个实例起作用。我可以演奏这个大提琴或那个大提琴,但我不能只是“演奏大提琴” “没有大提琴。您是否打算让这些函数针对类的实例进行操作?如果是这样,那么您必须针对这些实例构造函数指针;如果没有,那么你必须使用静态成员函数。
  • 我不明白的是:很多QWidgets 都有用于特定目的的鼠标事件处理程序。覆盖它们将使这些小部件至少在交互方面无法使用。抛开这个问题......如果你想处理例如您的应用程序的任何小部件的鼠标事件,您可以考虑为您的主窗口安装一个事件过滤器。 Qt doc. Event Filters
  • @Beta 我明白你在说什么,但在创建实例之前我不会调用这些方法。我只是告诉软件“看,当你有一把吉他时,这就是你在发生这种情况时弹奏它的方式”——而要做到这一点,我实际上不应该需要吉他,我不认为。我只需要某种方式来引用“弹吉他”。简而言之,我只需要参考方法即可根据我选择的工具轻松访问要做什么。

标签: c++ qt methods function-pointers class-members


【解决方案1】:

您可以将函数指针用于常规函数或静态类方法:

void foo(int) {/**/}
struct S
{
    static void bar(int) {/**/}
};

// and then

main()
{
    void (*f1)(int) = &foo;
    void (*f2)(int) = &S::bar;

    f1(42); // calls foo(42)
    f2(42); // calls S::bar(42)
}

方法指针可用于非静态类方法

struct S
{
    void bar(int) {/**/}
};

// and then

main()
{
    void (S::*m)(int) = &S::bar;

    S s;

    (s.*m)(42); // call s.bar(42);
}

std::function 是另一种选择:

struct S
{
    void bar(int) {/**/}
};

// and then

main()
{
    std::function<void (S*, int)> f1 = &S::bar;
    S s;
    std::function<void (int)> f2 = [&s](int i) { s.bar(i); }
    std::function<void ()> f3 = [&s]() { s.bar(43); }

    f1(&s, 42);
    f2(42);
    f3();
}

【讨论】:

    【解决方案2】:

    void * 不是保存函数指针的正确类型。

    非静态成员类型除了它们的签名之外也绑定到类类型。在以下示例中,指向foo 的指针是void (A::*)(int) 类型。你当然可以有一个集合,例如QMap,来保存这样的指针:QMap&lt;QString, void (A::*)(int)&gt; collection;

    struct A {
        void foo(int a);
    };
    

    此外,为了使事情更简单,您可以为该类型命名:

    struct A {
        using MethodPointer = void (A::*)(int);
        void foo(int a);
    };
    

    QMap&lt;QString, A::MethodPointer&gt; collection;


    然而静态成员函数和普通函数一样:

    struct A {
        static void foo(int a);
    };
    

    这里指向foo 的指针是void (*)(int) 类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-27
      • 2019-09-11
      相关资源
      最近更新 更多