[英]std::async can't call protected base class method
I want to make a derived class that can call a base class method using std::async. 我想制作一个派生类,可以使用std :: async调用基类方法。 When I try to do this I get a compiler message saying it is protected, but I am passing "this" as the instance which is a derived class of the function I want to execute.
当我尝试执行此操作时,我收到一条编译器消息,指出它已受到保护,但是我将“ this”作为实例传递,该实例是我要执行的函数的派生类。
Here is my MCVE: 这是我的MCVE:
#include <iostream>
#include <thread>
#include <future>
class Base
{
protected:
bool threadFunc()
{
std::cout << "threadFunc called" << std::endl;
return true;
}
};
class Derived : public Base
{
public:
void callBaseMethodAsync()
{
std::future<bool> results = std::async(std::launch::async, &Base::threadFunc, this);
}
};
int main()
{
Derived test;
test.callBaseMethodAsync();
}
Which results in this compiler error message with gcc 4.8: 使用gcc 4.8会导致此编译器错误消息:
g++ -o source.o -c -std=c++11 source.cpp
source.cpp: In member function 'void Derived::callBaseMethodAsync()':
source.cpp:8:10: error: 'bool Base::threadFunc()' is protected
bool threadFunc()
^
source.cpp:20:75: error: within this context
std::future<bool> results = std::async(std::launch::async, &Base::threadFunc, this);
Why is std::async making a protected method not accessible from the derived class? 为什么std :: async使受保护的方法无法从派生类访问? What are some alternate ways to achieve using async to call the base class method from the derived class?
使用异步从派生类调用基类方法有哪些替代方法?
You have to use &Derived::threadFunc
instead of &Base::threadFunc
, because you have to use the class of the current context when the member function is protected in the base class. 您必须使用
&Derived::threadFunc
而不是&Base::threadFunc
,因为当成员函数在基类中受保护时,必须使用当前上下文的类。
(Update: This has nothing to do with the this
pointer type as I wrote earlier. This was nonsense.) (更新:这和我之前写的
this
指针类型无关。这是胡扯。)
LLVM even explains how to fix this in the error message: LLVM甚至在错误消息中说明了解决方法:
ov@abook:~/tmp>g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 10.0.0 (clang-1000.11.45.5)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
ov@abook:~/tmp>g++ -std=c++11 t.cpp
t.cpp:20:75: error: 'threadFunc' is a protected member of 'Base'
std::future<bool> results = std::async(std::launch::async, &Base::threadFunc, this);
^
t.cpp:8:14: note: must name member using the type of the current context 'Derived'
bool threadFunc()
^
1 error generated.
There is a special rule regarding protected member access. 有一个关于受保护成员访问的特殊规则。
Derived
does not have the unconditional ability to access protected members of its base class. Derived
没有无条件的能力来访问其基类的受保护成员。 In the case of taking a pointer-to-member, it has to use itself as the class (or a derived class of Derived
), and not Base
. 如果采用成员指针,则必须将自身用作类(或
Derived
的派生类),而不是Base
。 The standard reference is [class.protected]/1: 标准参考为[class.protected] / 1:
An additional access check beyond those described earlier in Clause 14 is applied when a non-static data member or non-static member function is a protected member of its naming class (14.2).
当非静态数据成员或非静态成员函数是其命名类(14.2)的受保护成员时,将应用除第14章中所述之外的其他访问检查。 As described earlier, access to a protected member is granted because the reference occurs in a friend or member of some class
C
.如前所述,授予访问受保护成员的权限,因为该引用发生在某个
C
类的朋友或成员中。 If the access is to form a pointer to member (8.3.1), the nested-name-specifier shall denoteC
or a class derived fromC
.如果访问要形成指向成员(8.3.1)的指针,则嵌套名称说明符应表示
C
或从C
派生的类。 All other accesses involve a (possibly implicit) object expression (8.2.5).所有其他访问都涉及一个(可能是隐式的)对象表达式(8.2.5)。 In this case, the class of the object expression shall be
C
or a class derived fromC
.在这种情况下,对象表达式的类应为
C
或从C
派生的类。
In other words, you have to write &Derived::threadFunc
instead of &Base::threadFunc
. 换句话说,您必须编写
&Derived::threadFunc
而不是&Base::threadFunc
。 Name lookup will find threadFunc
in Base
, but the resulting pointer-to-member can only be used on an object of type Derived
or a more derived class. 名称查找将在
Base
找到threadFunc
,但是生成的指向成员的指针只能在Derived
类型或更多派生类的对象上使用。 This allows a Derived
object to use threadFunc
to access its own internals that are part of Base
, but prevents it from observing those internals in other classes derived from Base
. 这允许
Derived
对象使用threadFunc
访问属于Base
自身内部,但是阻止其观察从Base
派生的其他类中的内部。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.