std :: async не может вызвать метод защищенного базового класса - PullRequest
0 голосов
/ 14 февраля 2019

Я хочу создать производный класс, который может вызывать метод базового класса, используя std :: async.Когда я пытаюсь сделать это, я получаю сообщение компилятора о том, что оно защищено, но я передаю «this» как экземпляр, являющийся производным классом функции, которую я хочу выполнить.

Вот мой 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();
}

, что приводит к сообщению об ошибке компилятора с 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);

Почему std :: async делает защищенный методне доступны из производного класса?Каковы некоторые альтернативные способы использования async для вызова метода базового класса из производного класса?

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Существует специальное правило в отношении защищенного доступа членов.Derived не имеет безусловной возможности доступа к защищенным членам своего базового класса.В случае получения указателя на член он должен использовать себя в качестве класса (или производного класса Derived), а не Base.Стандартная ссылка [class.protected] / 1:

Дополнительная проверка доступа, помимо описанной ранее в разделе 14, применяется, когда нестатический элемент данных или функция нестатического члена является защищеннойчлен своего класса именования (14.2).Как описано ранее, доступ к защищенному члену предоставляется, поскольку ссылка встречается у друга или члена некоторого класса C.Если доступ должен формировать указатель на член (8.3.1), спецификатор вложенного имени должен обозначать C или класс, производный от C.Все другие обращения включают (возможно, неявное) выражение объекта (8.2.5).В этом случае класс выражения объекта должен быть C или класс, производный от C.

Другими словами, вы должны написать &Derived::threadFunc вместо &Base::threadFunc.Поиск имени найдет threadFunc в Base, но результирующий указатель на член может использоваться только для объекта типа Derived или более производного класса.Это позволяет объекту Derived использовать threadFunc для доступа к его собственным внутренним элементам, которые являются частью Base, но не позволяет ему наблюдать эти внутренние объекты в других классах, полученных из Base.

0 голосов
/ 14 февраля 2019

Вы должны использовать &Derived::threadFunc вместо &Base::threadFunc, потому что вы должны использовать класс текущего контекста, когда функция-член защищена в базовом классе.

(Обновление: в этом нет ничегоделать с указателем типа this, как я писал ранее. Это нонсенс.)

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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...