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

Имам програма, в която трябва да направя базов клас, който се споделя между 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. Има ли някакъв начин да се заобиколи това или нещо не съм разбрал? Мога да направя променливите 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