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

У меня есть программа, в которой мне нужно создать базовый класс, который разделяется между 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. Есть ли способ обойти это или я что-то не понимаю? Я могу сделать базовые переменные общедоступными, но это было бы плохо, поскольку в моем реальном экземпляре это кусок выделенной памяти и семафоры для защиты ее от многопоточности.

Помощь?


person David Snape    schedule 05.09.2011    source источник
comment
возможный дубликат доступа к защищенным переменным родителя. Это не конкретно о том, является ли функция static, но потому, что параметр, через который осуществляется доступ к базовому члену, не относится к типу Derived.   -  person CB Bailey    schedule 05.09.2011
comment
Аргумент статической функции должен относиться к базовому классу, чтобы соответствовать требованиям вызова указателя функции. Может быть, я смогу обойти это с помощью динамического приведения   -  person David Snape    schedule 05.09.2011
comment
Если вы можете контролировать, что функция вызывается только с указателями на Base объекты, которые являются подобъектами базового класса Derived объектов, вы можете использовать static_cast для преобразования из Base* в Derived* в теле функции. В противном случае вам пришлось бы быть friend из Base, иначе вы могли бы сделать var общедоступным. Если вы не можете сделать ничего из этого, вы застряли.   -  person CB Bailey    schedule 05.09.2011


Ответы (2)


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

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...
    }
} ;
person James Kanze    schedule 05.09.2011
comment
Итак, я предполагаю, что поскольку моя статическая функция используется для указателя функции, а аргумент должен быть базовым классом, я должен иметь возможность динамически преобразовывать в производный класс. - person David Snape; 05.09.2011
comment
Если в базовом классе есть хотя бы одна виртуальная функция, да. (Или вы можете изменить функцию так, чтобы она принимала Derived*, а dynamic_cast оставила на усмотрение клиента.) - person James Kanze; 05.09.2011

Спецификатор доступа применяется к дескриптору класса Derived (ссылка / указатель / объект), а не к методам самого класса 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;
person iammilind    schedule 05.09.2011
comment
К сожалению, в моем реальном классе данные в базовом классе на самом деле представляют собой некоторые блоки памяти и загрузку семафоров для многопоточного доступа. Использование геттеров и сеттеров для семафоров и куска памяти кажется очень громоздким, поскольку в базе может быть 10-15 переменных. - person David Snape; 05.09.2011