C++ Access private member of nested class - c++

The title might be a bit misleading. I have the following problem: I have a tree consisting of leaves and internal nodes. The user should be able to store any information in the leaves and the tree has some methods which get a set of user-defined values and need to access the corresponding leaves in constant time (not amortized).
I came up with the following idea but it does not work because unfortunately I cannot access private members of a nested class: The user creates the tree and also for each leaf an instance of UserElement which contains the user_defined value for the corresponding leaf. Once a method like doSomethingWithTheTree(list>) is called and the tree is built, the tree creates the corresponding leaves and saves it in the private field leaf. Whenever the user wants to call a method with some of the leaves corresponding to its user_defined values, he/she just has to call the method by giving the corresponding UserElements and the tree can retrieve the corresponding leaves in constant time.
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
}
}

Technically, that's a nested class (declared within another class), not a subclass (which inherits from its superclass).
You can allow the Tree class to access its privates by making it a friend:
class UserElement {
friend class Tree;
// ...
};
or, for better encapsulation, you could restrict access only to the member function(s) that need it, although it gets a bit messy due to the need to declare things in the right order:
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>>);
// ...
};
};

You may do
class Outer {
private: // maybe protected:
class Inner {
public:
....
};
};
or
class Outer {
public:
class Inner {
friend class Outer;
private:
....
};
};

You can declare class Tree a friend to UserElement<>, which would allow Tree to access all members of UserElement<>.

Related

Inner class inside outer template class in C++17

I have a class template containing an inner class. I want the outer class to be the only one able to construct objects of the inner class but I need to expose the inner class to the outside so others can call a public method of its own.
Outer also defines a public interface for callback actions, in which it is supposed to provide an object of type Inner to the callee. So Outer must construct an Inner object and pass it as parameter in the callback method.
For example:
template<typename T>
class Outer {
public:
virtual void callbackMethod(std::shared_ptr<Outer<T>::Inner> inner) = 0;
class Inner {
private:
Obj obj;
Inner(...) {} // init obj, a private member of another type
std::shared_ptr<Inner> createInner() {
std::shared_ptr<Inner> inner = std::make_shared<Inner>(...);
... /* do some work */ ...
return inner;
}
public:
~Inner=default();
void exposedMethod() {
...
}
}
}
Under certain conditions, Outer creates an Inner object and calls the callback method, which is supposed to be implemented by someone else. The callee should then be able to do something like this:
inner->exposedMethod();
Of course, the idea is not letting outsiders to be able to construct Inner objects; this is why I designed Inner as a nested class and declared its constructor and creator methods as private.
My problem is that I need my Outer class to call createInner but the compiler complains about Outer trying to access private Inner constructor. I tried to declare Outer as friend inside Inner, but the error is still there:
class Inner {
friend class Outer<T>;
...
}
I have read that friendship follows other rules when applied to class templates. I am using clang with C++17.
So the question is, how could I design my classes so that class Outer can be the only one allowed to create objects of Inner type, it but at the same time be able to expose one of its methods to the outside? Please remember that Outer is a class template.
By the way, I don't care if the solution requires Inner to be a first-level class.
Thanks a lot.
A straightforward solution that doesn't require friending make_shared is lock-and-key:
template<typename T>
class Outer {
struct Inner_key{ explicit Inner_key() = default; };
public:
virtual void callbackMethod(std::shared_ptr<Outer<T>::Inner> inner) = 0;
class Inner {
private:
Obj obj;
public:
Inner(Inner_key, ...) {} // init obj, a private member of another type
std::shared_ptr<Inner> createInner(Inner_key key) {
std::shared_ptr<Inner> inner = std::make_shared<Inner>(key, ...);
... /* do some work */ ...
return inner;
}
~Inner=default();
void exposedMethod() {
...
}
}
}
Now anywhere in the program (including std::make_shared) can lookup Inner::createInner and Inner::Inner, but they can't be called without creating an Inner_key instance, which being a private nested type, only Outer member functions can do.

Details and benefits of using a struct in a class definition

Consider the following code:
class myclass
{
public:
//some public stuff
private:
struct classitem
{
int x;
classitem *next;
};
}
What I do not understand is this;
Is classitem just a definition, or will it already be a member of an object of this class? In other words, will it be filling any memory when we create an object of this class? If it is just a definition, how would we use it in future?
And what would be the benefits of using this struct in class definition instead of defining it outside of the class?
It will be just a definition.
If you want an object, use:
struct T { ... } instance;
The inner struct will be scoped in the outer struct definition - as to why it's useful, you can make the type (class) definition private for instance, if you don't want that type to be used outside of your class.
class NHeadedBeast {
struct Head {
Head() : numHeads{2}, eyesPerHead{4} { }
int numHeads;
int eyesPerHead;
} head;
public:
int getEyeCount() const {
return head.eyesPerHead * head.numHeads;
}
};
Notice how specific the Head class is - and also, it's called Head, which has a decent chance of colliding with some other type name. In other words, noone would ever want to use that Head type without my NHeadedBeast class, so might as well make the type inaccessible and isolate it in the NHeadedBeast scope.

How can I make 2 c++ classes know about each other's data members?

My assignment is to make a class that acts like a standard library List. I am unable to get the iterator to work properly, because it must access the tail of the linked list when decrementing from the end. Here is a section of my header file:
typedef int T;//for now; eventually will be templated
class list;//**forward declaration, doesn't let other classes know about _tail.**
class Node
{
//this works fine; class definition removed to make post shorter
};
class list_iterator
{
private:
Node* _node;
list* _list;
public:
//constructor
list_iterator& operator--(){_node=_node?(_node->_prev):(_list->_tail);return *this;}
//some other declarations
};
class list
{
friend class list_iterator;
private:
Node/*<T>*/ *_head,***_tail**;
int _size;
public:
typedef list_iterator iterator;
//some constructors and other method declarations
iterator begin() const {iterator it(_head);return it;}
iterator end() const {iterator it(0);return it;}
//more method declarations
};
I tried to bold the important parts, but it is just surrounding them with asterisks.
NOTE: Most of the member functions are defined in the cpp file; they all happen to be removed for a short post.
You just need to move the method definition of operator-- out of the class and put it after list (or in the source file (probably a better idea. Leave the header file for declarations)).
Note: Leave the declaration inside list_iterator
class list_iterator
{
/* STUFF */
list_iterator& operator--();
};
class list
{
/* STUFF */
};
// Now list_iterator::operator-- can see all the members of list.
list_iterator& list_iterator::operator--()
{
_node=_node?(_node->_prev):(_list->_tail);
return *this;
}
Unlike what some other answers suggest. Friendship does NOT break encapsulation. In fact in increases encapsulation (when done correctly) by making the friend part of the classes interface. It does however tightly bind the friend to the class.
This is exactly what you want for iterators. For the iterator to work efficiently it needs to know the internals of the class so it is usually a friend (or an internal class). It increases the usability of the class without exposing the internal workings of the class at the cost that it tightly couples the iterator to the class (so if you change the class you will need to change the implementation of the iterator (but this is not unexpected)).
By far the easiest way is to nest the iterator inside the list class:
class list {
Node *head, *tail;
class iterator {
Node *node;
list *list;
// ...
};
};
If you don't want to do that, you'll need to split the implementations of both list and list_iterator into two pieces: first a class definition that only declares the member functions, then implementations of the member functions:
class list;
class list_iterator {
// ...
Node *n;
list *l;
};
class list {
// ...
friend class list_iterator;
};
inline list_iterator& list_iterator::operator--(){
_node=_node?(_node->_prev):(_list->_tail);
return *this;
}
This way, list has been declared by the time you define the list * in the definition of list_iterator. Then _tail has been defined in list, then you have the code in list_iterator::operator-- that actually needs to use list::_tail..

c++ handling derived class that's self referencing

So suppose I have a tree class like this in c++
class Node{
void addChild(Node*);
/*obvious stuff*/
protected:
Node* parent;
vector<Node*> children
}
class specialNode : public Node{
void addChild(specialNode*);
/*obvious stuff*/
/*special stuff*/
}
Now whenever I access the children in specialTree, I obviously get Node*, not specialNode*.
But this specialNode* has member variables and functions that Node doesn't have.
I can force specialNode to only have take specialNode as children and otherwise break in compile time,
but I still get Node* when accessing children/parent, and I have to cast it whenever I want to use special functions, even in specialNode functions.
Is there any clever, or just any better way to go about this?
Other than literally casting every time?
If you only need SpecialNode objects in your tree (and just want to encapsulate all generic tree functionality in Node) you can make Node a so called "mix-in" class like
template <class N>
class Node : public N {
public:
void addChild(Node<N>*);
protected:
Node<N>* parent;
vector<Node<N>*> children;
};
class SpecialNodeBase {
// Here comes all "special" data/methods for your "special" tree
};
typedef Node<SpecialNodeBase> SpecialNode;
After that you can construct a tree of SpecialNode objects and use all methods from SpecialNodeBase as well as additional tree-managing functions from Node
Because addChild function in your child class is not polymorphism, make it virtual, but overloading functions across base/child members is not allowed, so we have to change the addChild parameter in the child class:
class Node{
virtual void addChild(Node*);
...
}
class specialNode : public Node{
virtual void addChild(Node*);
...
}
Now, it should work.
If you want to access to the childeren variable from the child class (specialNode class), you should cast it. For example:
specialNode* var = static_cast<specialNode*>(children[i]);
Since we declared addChild as a virtual function, then we should use dynamic_cast instead of static_cast if we aren't sure that children[i] is always an instance of specialNode class, and thus it is better to use dynamic_cast:
specialNode* var = dynamic_cast<specialNode*>(children[i]);
if(var != NULL)
{
//...
}
If I understand correctly, the "Mix-in" class solution won't allow you to call addChild from functions implemented by SpecialNodeBaseClass.
You can actually do the following:
template <class recursiveT>
class Base {
public:
Base(dataType data) { populate children with data; }
void addChild() { something base class appropriate; }
protected:
std::vector<recursiveT> children;
};
class Derived: public Base<Derived> {
public:
/* note: the constructor here will actually call the
constuctor of the base class */
Derived(dataType data) : Base<Derived>(data) {}
/* other special functions go here. */
};
This may look a little crazy, but it compiles cleanly for me on several GCC versions so I'm inclined to believe it's not totally wrong-headed. You should now be able to call the functions of Base from inside Derived.
You will definitely have to cast the Node * to a specialNode * at some point, but you can make this clean and easy to manage by doing this in only one place. You could add a member function, say getParent and override it in specialNode, like this:
class Node {
...
virtual Node *getParent() {
return parent;
}
};
class specialNode : public Node {
...
specialNode *getParent() {
return dynamic_cast<specialNode *>(parent);
}
};
Of course, this is assuming that specialNodes always have other specialNodes as parent/children. If you mix Nodes and specialNodes, this obviously won't work.

Problem about C++ class (inheritance, variables scope and functions)

I have a class that contains some data: class DATA
Now I would to create some functions that uses those data. I can do it easily by writing member functions like DATA::usedata();
Since there are hundreds of functions, I would to keep an order in my code, so I would like to have some "categories" (not sure of the correct name) like:
DATA data;
data.memory.free();
data.memory.allocate();
data.file.import();
data.whatever.foo();
where memory, file and whatever are the "categories" and free, allocate and foo are the functions.
I tried the inheritance way, but I got lost since I can not declare inside DATA a memory or file object, error C2079 occurs: http://msdn.microsoft.com/en-us/library/9ekhdcxs%28VS.80%29.aspx
Since I am not a programmer please don't be too complicated and if you have an easier way I am all ears.
Give your data class some classes of its own, and let those classes refer to the data object that holds them. It sounds like you might have tried to do that already. If you got an error, then you were doing something else wrong.
struct DATA
{
struct DataMemory
{
DATA& data;
DataMemory(DATA& d): data(d) { }
void free();
void allocate();
};
struct DataFile
{
DATA& data;
DataFile(DATA& d): data(d) { }
void import();
};
struct DataWhatever
{
DATA& data;
DataWhatever(DATA& d): data(d) { }
void foo();
};
DataMemory memory;
DataFile file;
DataWhatever whatever;
DATA(): memory(*this), file(*this), whatever(*this) { }
};
Each of the inner classes has a member that's a reference to the containing DATA object. They have constructors to allow that member to get assigned. The DATA class itself also has a constructor to initialize each of its members with a reference to itself.
You can now implement the functions and refer to any of the DATA object's members.
void DATA::DataMemory::free()
{
data.whatever.foo();
}
The inner classes aren't required to be inner classes; they could be standalone top-level classes like DATA if you want, but I think nesting them helps show their interdependence.
The easiest way would be to do the categories just as a naming convention. If you replace the . with _ you don't need any "subobjects" and get:
data.memory_free();
data.memory_allocate();
data.file_import();
This way you basically have the same function names but avoid all the implementation problems of the subobject approach.
If you have a class that has hundreds of member functions, you almost certainly need to break that up into multiple classes. To achieve the type of naming syntax that you're after you could use name spaces to group related classes into "categories."
class DATA
{
public:
class CategoryA_Class
{
friend DATA;
private:
CategoryA_Class() { }
public:
bool GiveMeSomeInt() { return 1; }
};
class CategoryB_Class
{
friend DATA;
private:
CategoryB_Class() { }
public:
bool GiveMeSomeBool() { return true; }
};
public:
CategoryA_Class CategoryA;
CategoryB_Class CategoryB;
};
int _tmain(int argc, _TCHAR* argv[])
{
DATA mydata;
int a = mydata.CategoryA.GiveMeSomeInt();
bool b = mydata.CategoryB.GiveMeSomeBool();
return 0;
}
It is normal to feel confuse when you have so many functions in one class. The trick is to break it all up so that the information is contained in smaller classes that inherits a parent class that has common functions and data to all children.
From what I see you already found a common name for the information. class DATA can be that parent class. Now, you need to break up the information into types of Data. In other words, you will have children classes that will be specialized in something. A quick way to divide the information is to create a diagram of a parent class linked with children classes.
Here is a small example of what you could do:
//parent class
template <class T> class Data
{
T data_; //you could use an array like a std::vector or
//use a stream
public:
//...
void foo();
T getData() const;
};
//child class
template <class T> class Memory
: public Data
{
public:
void free();
void allocate(T data);
//...
};
//child class
template <class T> class File
: public Data
{
public:
T readFile(); //could read the contents of a
//file and save it in data_ (class member from parent class)
void writeFile(); //could write data_
//(class member from parent class) to a file
//...
};
Also, here is documentation if you need help on the concept of inheritance.