#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>
{
};
Моя идея заключается в том, что:
BarDerived
установит статическоеt
значение вFooDerived
FooDerived
наследуетFoo<BarDerived>
, который является другомBarDerived
- Поскольку
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);
^
Я что-то пропустил в том, как я ожидал, что шаблоны / friendship будут вести себя?
Комментарии:
1. Имя
T::t
защищено, вы не можете получить к нему прямой доступBar<..>
, поскольку этот класс не является другомfoo
. Вы должны сделать это имя доступным дляBar<..>
viaBarDerived
или befriendBar<..>
напрямую.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, а не за базу.