简体   繁体   English

std :: async无法调用受保护的基类方法

[英]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 denote C or a class derived from C . 如果访问要形成指向成员(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 from C . 在这种情况下,对象表达式的类应为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.

相关问题 派生类无法访问基类的受保护方法 - Derived class can't access protected method of base class 无法通过Diamond中的std :: unique_ptr访问最基类的受保护成员变量 - Can't access protected member variables of the most base class through std::unique_ptr in diamond 为什么不能在派生类重写函数中调用受保护的虚拟基类函数? - Why can't I call protected virtual base class function in the derived class overridden function? 无法从派生类访问基类中的受保护成员 - Can't access protected member in base class from derived class 我可以std :: bind一个基类的构造函数,以便派生类不需要显式调用它吗? - Can I std::bind a base class' constructor so that the derived doesn't need to call it explicitly? 有没有希望在 std::variant 上有效地调用公共基础 class 方法? - Is there any hope to call a common base class method on a std::variant efficiently? std :: bind和对基类方法的非虚拟调用 - std::bind and non-virtual call to base class method 我无法访问我的基础 class 的受保护成员 - I can't access to the protected member of my base class 派生类中的静态方法可以在C ++中调用受保护的构造函数吗? - Can a static method in a derived class call a protected constructor in C++? 为什么我不能使用受保护/私有继承在派生实例中访问基类的受保护成员? - Why can't I access protected members of base class in derived instances using protected/private inheritance?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM