Могу ли я получить доступ к элементам, защищенным базовыми классами, от статической функции в производном классе?

У меня есть программа, в которой мне нужно создать базовый класс, который используется совместно с dll и некоторым кодом приложения. Тогда у меня есть два разных производных класса: один в dll в основном приложении. Каждый из них имеет некоторые статические функции-члены, которые работают с данными в классе nase. (Они должны быть статическими, поскольку они используются в качестве указателей на функции в другом месте). В самой простой форме моя проблема показана ниже.

class Base {
protected:
  int var ;
};

class Derived : public Base {
  static bool Process( Base *pBase ) {
    pBase->var = 2;
    return true;
  }
};

Мой компилятор жалуется, что я не могу получить доступ к защищенным членам pBase, хотя Derived защитил доступ к Base. Есть ли способ обойти это или я что-то не понимаю? Я могу сделать базовые переменные общедоступными, но это было бы плохо, поскольку в моем реальном примере это кусок выделенной памяти и семафоров, чтобы защитить ее для многопоточности.

Справка

Ответы

Ответ 1

В целом (независимо от того, является ли эта функция статической или нет), функция-член производного класса может получить доступ только к защищенной базе членов класса объектов его типа. Он не может получить доступ к защищенным члены базы, если статический тип не относится к производному классу (или производный от него класс). Итак:

class Base {
protected:
    int var;
 } ;

class Derived : public Base {
    static void f1( Derived* pDerived )
    {
        pDerived->var = 2; // legal, access through Derived...
    }
    static bool Process( Base *pBase )
    {
        pBase->var = 2 ;  // illegal, access not through Derived...
    }
} ;

Ответ 2

Спецификатор доступа применяется к дескриптору класса Derived (reference/pointer/object), а не к методам самого класса Derived. Даже если метод не был static, вы попали бы в ту же ошибку. Потому что вы не получаете доступ к var с помощью производного дескриптора. Демо.

Правильный способ - предоставить метод setter:

class Base {
protected:
  int var ;
public:
  void setVar(const int v) { var = v; } // <--- add this method
};

Примечание. Есть еще один выход, но я не уверен, что он изящный.

(static_cast<Derived*>(pBase))->var = 2;