Наследование от класса с параметром шаблона friend

#c #c 11

#c #c 11

Вопрос:

Я пытаюсь сделать следующее: у меня есть класс, и всякий раз, когда я объявляю новый экземпляр этого класса, я хочу установить статическую переменную в другом классе. Я пытаюсь сделать это с помощью шаблонов, чтобы я мог сделать что-то вроде class C : public D<AA, BB, CC, DD> (используя переменные параметры). Проблема в том, что статическая переменная классов AA, BB, CC, DD (все они имеют одну и ту же базу) защищена. Итак, я пытаюсь подружиться C с классами, чтобы он мог получить доступ к переменной.

Что я пробовал, так это:

 template <class T>
class Foo
{
    protected:
    static T* t;
    friend T;
};
template <class T>
T* Foo<T>::t = nullptr;
  

Сначала я объявил базовый класс Foo, который имеет статическую переменную и объявление friend . Это предназначено для наследования другими классами.

Затем я сделал это:

 template <class Self, class T> //T = Type derived from Foo
struct Bar
{
    Bar()
    {
        T::t = static_cast<Self*>(this);
    }
};
  

Какой класс при создании экземпляра установит статическую переменную в типе T .

И это окончательная реализация:

 struct FooDerived;

struct BarDerived : public Bar<BarDerived, FooDerived>
{

};

struct FooDerived : public Foo<BarDerived>
{

};
  

Моя идея заключается в том, что:

  1. BarDerived установит статическое t значение в FooDerived
  2. FooDerived наследует Foo<BarDerived> , который является другом BarDerived
  3. Поскольку BarDerived является другом Foo<BarDerived> , он может получить доступ Foo<BarDerived>::t

Но это не работает, и я получаю следующую ошибку компиляции:

 prog.cpp: In instantiation of ‘void Bar<Self, T>::test() [with Self = BarDerived; T = FooDerived]’:
prog.cpp:37:9:   required from here
prog.cpp:11:4: error: ‘BarDerived* Foo<BarDerived>::t’ is protected
 T* Foo<T>::t = nullptr;
    ^
prog.cpp:18:8: error: within this context
   T::t = static_cast<Self*>(this);
        ^
  

(https://ideone.com/jcRcH0 )

Я что-то пропустил в том, как я ожидал, что шаблоны / friendship будут вести себя?

Комментарии:

1. Имя T::t защищено, вы не можете получить к нему прямой доступ Bar<..> , поскольку этот класс не является другом foo . Вы должны сделать это имя доступным для Bar<..> via BarDerived или befriend Bar<..> напрямую.

2. ИМХО дизайн довольно запутанный.

3. @dyp Я сделал это, чтобы упростить работу по созданию баров и их связей с Foos, вы думаете, это можно было сделать по-другому?

Ответ №1:

Вы можете использовать следующее: https://ideone.com/RW3xfV

 template <class T>
class Foo
{
protected:
    static T* t;
    template <class Self, class U> //T = Type derived from Foo
    friend struct Bar;
};
  

поскольку это Bar то, к чему требуется доступ Foo<T>::t .

Комментарии:

1. Спасибо, я думал, что BarDerived отвечает за настройку Foo::t, а не за базу.