Название может быть немного вводящим в заблуждение. У меня следующая проблема: у меня есть дерево, состоящее из листьев и внутренних узлов. Пользователь должен иметь возможность хранить любую информацию в листьях а также В дереве есть несколько методов, которые получают набор пользовательских значений и нуждаются в доступе к соответствующим листам в постоянное время (не амортизируется).
Мне пришла в голову следующая идея, но она не работает, потому что, к сожалению, я не могу получить доступ к закрытым членам вложенного класса: пользователь создает дерево а также также для каждого листа экземпляр UserElement
который содержит значение user_defined для соответствующего листа. После вызова метода, подобного doSomethingWithTheTree (list>), и построения дерева, дерево создает соответствующие листья и сохраняет его в закрытом поле. leaf
, Всякий раз, когда пользователь хочет вызвать метод с некоторыми листьями, соответствующими его значениям user_defined, он или она просто должен вызвать метод, передав соответствующий UserElement
и дерево может получить соответствующие листья за постоянное время.
class Tree {
public:
template <typename T>
class UserElement {
private:
T user_value;
tree_node* leaf; // this has to be private for
// everyone outside the class `Tree`
public:
T getInf() {
return user_value;
}
void setInf(T i) {
user_value = i;
}
};
void doSomethingWithTheTree(list<UserElement<T>> elements) {
...
// I want to be able to access elem.leaf for all elements
}
}
Технически это вложенный класс (объявлено в другом классе), а не подкласс (который наследует от своего суперкласса).
Вы можете позволить классу Tree получить доступ к его частным лицам, сделав его другом:
class UserElement {
friend class Tree;
// ...
};
или, для лучшей инкапсуляции, вы могли бы ограничить доступ только к функциям-членам, которые нуждаются в этом, хотя это становится немного запутанным из-за необходимости объявлять вещи в правильном порядке:
class Tree {
public:
// Declare this so we can declare the function
template <typename T> class UserElement;
// Declare this before defining `UserElement` so we can use it
// in the friend declaration
template <typename T>
void doSomethingWithTheTree(list<UserElement<T>> elements) {
elements.front().leaf;
}
template <typename T>
class UserElement {
// Finally, we can declare it a friend.
friend void Tree::doSomethingWithTheTree<T>(list<UserElement<T>>);
// ...
};
};
Вы можете сделать
class Outer {
private: // maybe protected:
class Inner {
public:
....
};
};
или же
class Outer {
public:
class Inner {
friend class Outer;
private:
....
};
};
Вы можете объявить class Tree
friend
в UserElement<>
, что позволило бы Tree
чтобы получить доступ все Члены UserElement<>
,