C++ 非静态成员函数的使用无效

C++ 非静态成员函数的使用无效,c++,qt,qt5,C++,Qt,Qt5,在我的Qt应用程序中,当用户按下快捷键时,我希望能够将选项卡添加到非静态的QTabWidget。通常我会这样实现它: File.addAction("Settings", openSettings, Qt::ALT + Qt::Key_S); 其中,File是一个QTabWidget,openSettings是一个静态方法。唯一的问题是它只适用于静态方法,问题是我不能在静态方法中访问非静态变量。因此,我认为由于Qt要求函数为静态函数,因此我可以实例化静态std::function对象: sta

在我的Qt应用程序中,当用户按下快捷键时,我希望能够将选项卡添加到非静态的
QTabWidget
。通常我会这样实现它:

File.addAction("Settings", openSettings, Qt::ALT + Qt::Key_S);
其中,
File
是一个
QTabWidget
openSettings
是一个静态方法。唯一的问题是它只适用于静态方法,问题是我不能在静态方法中访问非静态变量。因此,我认为由于Qt要求函数为静态函数,因此我可以实例化静态
std::function
对象:

static std::function<void(void)> openSettings_ = []() { openSettings; };
问题在于,它会产生以下错误:

Error: invalid use of non-static member function 'void window::openSettings()'

我的理由是,我熟悉C语言,并假设Qt调用的函子与函数指针几乎相同,而函数指针基本上是一个对象。因此,我假设,如果我要实例化一个类型为
std::function
的静态对象,该对象指向/执行一个非静态函数,我就可以绕过这个问题,但情况显然不是这样。鉴于我当前的思维过程是错误的,我该怎么做呢?

首先,立即出现的错误是因为您实际上没有调用该函数。您必须调用它:
openSettings()

然而,这是行不通的<代码>打开设置
是非静态成员函数。所有这样的普通成员函数都使用隐式
this
指针指向调用它们的对象。这意味着如果没有要调用的对象,就不能直接调用
openSettings
函数。但是
您编写的lambda没有捕获到这个
,这意味着没有这样的对象

这可以通过在lambda中捕获
This
来解决,例如
auto-openSettings_=[This](){This->openSettings();}

但另一方面,这个函数就像一个插槽。您应该使用标准信号/插槽语法将感兴趣的信号直接附加到信号,而不是编写单独的函子。可能是这样的

File.addAction("Settings", this, &(decltype(*this))::openSettings, Qt::ALT + Qt::Key_S);

(请注意,我使用的是
decltype
,因为我不确定这
*是什么类型。您可以用类的名称替换。)

首先,由于您没有实际调用函数,因此会立即出现错误。您必须调用它:
openSettings()

然而,这是行不通的<代码>打开设置
是非静态成员函数。所有这样的普通成员函数都使用隐式
this
指针指向调用它们的对象。这意味着如果没有要调用的对象,就不能直接调用
openSettings
函数。但是
您编写的lambda没有捕获到这个
,这意味着没有这样的对象

这可以通过在lambda中捕获
This
来解决,例如
auto-openSettings_=[This](){This->openSettings();}

但另一方面,这个函数就像一个插槽。您应该使用标准信号/插槽语法将感兴趣的信号直接附加到信号,而不是编写单独的函子。可能是这样的

File.addAction("Settings", this, &(decltype(*this))::openSettings, Qt::ALT + Qt::Key_S);

(请注意,我使用的是
decltype
,因为我不确定这
*是什么类型。您可以用类的名称替换。)

是否忘记调用该函数?另外,您必须在lambda中捕获
这个
,以直接调用非静态成员函数。我该如何做呢?像这样<代码>静态std::函数openSettings_=[](){openSettings(this);}那将是:
autoopensettings_=[this](){this->openSettings();},请参阅我的答案<代码>[]
指定“捕获列表”,即捕获以供lambda内部使用的对象集。是否忘记调用该函数?另外,您必须在lambda中捕获
这个
,以直接调用非静态成员函数。我该如何做呢?像这样<代码>静态std::函数openSettings_=[](){openSettings(this);}那将是:
autoopensettings_=[this](){this->openSettings();},请参阅我的答案<代码>[]
指定“捕获列表”,即捕获以供lambda内部使用的对象集。上一个建议不起作用,或者可能是我对如何执行的解释错误;但是你的第一个建议非常有效。请您解释一下什么是
auto
以及为什么需要
[此]
auto
指示C++11或更高版本的编译器推断出正确的对象类型。它节省了打字,更灵活,而且不容易出错<代码>此
在捕获列表中是必需的,因为默认情况下不会自动捕获它。这是C++后来的标准(可能是C++ 17,但我记不起来)所要解决的缺点。尝试第二种方法时出现了什么错误?如果我将其更改为函数的正确类型
&window
,则会产生错误
错误:没有匹配的函数用于调用QMenu::addAction(const char[9],window*,void(window:*)(),unsigned int
您使用的是哪个版本的Qt?
window
QWidget
的子类吗?我使用的是5.12版,是ubuntu repo中最新的版本。
window
实际上是
QMainWindow
的扩展,尽管它定义了诸如CenterWidget之类的东西。上一个建议不起作用,或者也许我对如何做的解释是错误的,但是你的第一个建议非常有效。你介意解释一下什么是
auto
,为什么是
[这个]
是必需的?
auto
指示C++11或更高版本的编译器推断对象的正确类型。它节省了键入时间,更灵活,更不容易出错。
在捕获列表中是必需的,因为def不会自动捕获它