Can someone please point me towards some nice resources for understanding and using nested classes? I have some material like Programming Principles and things like this IBM Knowledge Center - Nested Classes
But I'm still having trouble understanding their purpose. Could someone please help me?
Nested classes are cool for hiding implementation details.
List:
class List
{
public:
List(): head(nullptr), tail(nullptr) {}
private:
class Node
{
public:
int data;
Node* next;
Node* prev;
};
private:
Node* head;
Node* tail;
};
Here I don't want to expose Node as other people may decide to use the class and that would hinder me from updating my class as anything exposed is part of the public API and must be maintained forever. By making the class private, I not only hide the implementation I am also saying this is mine and I may change it at any time so you can not use it.
Look at std::list or std::map they all contain hidden classes (or do they?). The point is they may or may not, but because the implementation is private and hidden the builders of the STL were able to update the code without affecting how you used the code, or leaving a lot of old baggage laying around the STL because they need to maintain backwards compatibility with some fool who decided they wanted to use the Node class that was hidden inside list.
Nested classes are just like regular classes, but:
they have additional access restriction (as all definitions inside a class definition do),
they don't pollute the given namespace, e.g. global namespace. If you feel that class B is so deeply connected to class A, but the objects of A and B are not necessarily related, then you might want the class B to be only accessible via scoping the A class (it would be referred to as A::Class).
Some examples:
Publicly nesting class to put it in a scope of relevant class
Assume you want to have a class SomeSpecificCollection which would aggregate objects of class Element. You can then either:
declare two classes: SomeSpecificCollection and Element - bad, because the name "Element" is general enough in order to cause a possible name clash
introduce a namespace someSpecificCollection and declare classes someSpecificCollection::Collection and someSpecificCollection::Element. No risk of name clash, but can it get any more verbose?
declare two global classes SomeSpecificCollection and SomeSpecificCollectionElement - which has minor drawbacks, but is probably OK.
declare global class SomeSpecificCollection and class Element as its nested class. Then:
you don't risk any name clashes as Element is not in the global namespace,
in implementation of SomeSpecificCollection you refer to just Element, and everywhere else as SomeSpecificCollection::Element - which looks +- the same as 3., but more clear
it gets plain simple that it's "an element of a specific collection", not "a specific element of a collection"
it is visible that SomeSpecificCollection is also a class.
In my opinion, the last variant is definitely the most intuitive and hence best design.
Let me stress - It's not a big difference from making two global classes with more verbose names. It just a tiny little detail, but imho it makes the code more clear.
Introducing another scope inside a class scope
This is especially useful for introducing typedefs or enums. I'll just post a code example here:
class Product {
public:
enum ProductType {
FANCY, AWESOME, USEFUL
};
enum ProductBoxType {
BOX, BAG, CRATE
};
Product(ProductType t, ProductBoxType b, String name);
// the rest of the class: fields, methods
};
One then will call:
Product p(Product::FANCY, Product::BOX);
But when looking at code completion proposals for Product::, one will often get all the possible enum values (BOX, FANCY, CRATE) listed and it's easy to make a mistake here (C++0x's strongly typed enums kind of solve that, but never mind).
But if you introduce additional scope for those enums using nested classes, things could look like:
class Product {
public:
struct ProductType {
enum Enum { FANCY, AWESOME, USEFUL };
};
struct ProductBoxType {
enum Enum { BOX, BAG, CRATE };
};
Product(ProductType::Enum t, ProductBoxType::Enum b, String name);
// the rest of the class: fields, methods
};
Then the call looks like:
Product p(Product::ProductType::FANCY, Product::ProductBoxType::BOX);
Then by typing Product::ProductType:: in an IDE, one will get only the enums from the desired scope suggested. This also reduces the risk of making a mistake.
Of course this may not be needed for small classes, but if one has a lot of enums, then it makes things easier for the client programmers.
In the same way, you could "organise" a big bunch of typedefs in a template, if you ever had the need to. It's a useful pattern sometimes.
The PIMPL idiom
The PIMPL (short for Pointer to IMPLementation) is an idiom useful to remove the implementation details of a class from the header. This reduces the need of recompiling classes depending on the class' header whenever the "implementation" part of the header changes.
It's usually implemented using a nested class:
X.h:
class X {
public:
X();
virtual ~X();
void publicInterface();
void publicInterface2();
private:
struct Impl;
std::unique_ptr<Impl> impl;
}
X.cpp:
#include "X.h"
#include <windows.h>
struct X::Impl {
HWND hWnd; // this field is a part of the class, but no need to include windows.h in header
// all private fields, methods go here
void privateMethod(HWND wnd);
void privateMethod();
};
X::X() : impl(new Impl()) {
// ...
}
// and the rest of definitions go here
This is particularly useful if the full class definition needs the definition of types from some external library which has a heavy or just ugly header file (take WinAPI). If you use PIMPL, then you can enclose any WinAPI-specific functionality only in .cpp and never include it in .h.
I don't use nested classes much, but I do use them now and then. Especially when I define some kind of data type, and I then want to define a STL functor designed for that data type.
For example, consider a generic Field class that has an ID number, a type code and a field name. If I want to search a vector of these Fields by either ID number or name, I might construct a functor to do so:
class Field
{
public:
unsigned id_;
string name_;
unsigned type_;
class match : public std::unary_function<bool, Field>
{
public:
match(const string& name) : name_(name), has_name_(true) {};
match(unsigned id) : id_(id), has_id_(true) {};
bool operator()(const Field& rhs) const
{
bool ret = true;
if( ret && has_id_ ) ret = id_ == rhs.id_;
if( ret && has_name_ ) ret = name_ == rhs.name_;
return ret;
};
private:
unsigned id_;
bool has_id_;
string name_;
bool has_name_;
};
};
Then code that needs to search for these Fields can use the match scoped within the Field class itself:
vector<Field>::const_iterator it = find_if(fields.begin(), fields.end(), Field::match("FieldName"));
One can implement a Builder pattern with nested class. Especially in C++, personally I find it semantically cleaner. For example:
class Product{
public:
class Builder;
}
class Product::Builder {
// Builder Implementation
}
Rather than:
class Product {}
class ProductBuilder {}
I think the main purpose of making a class to be nested instead of just a friend class is the ability to inherit nested class within derived one. Friendship is not inherited in C++.
You also can think about first class ass type of main function, where You initiate all needed classes to work togheter. Like for example class Game, initiate all other classes like windows, heroes, enemy's, levels and so on. This way You can get rid all that stuff from main function it self. Where You can create obiect of Game, and maybe do some extra external call not related to Gemente it self.
Related
I'd like to alias a method of a base class in a derived method in C++ -- i.e. change only the name, not the signature.
The method's name is clear enough in its original scope (in the base class), but becomes ambiguous or misleading in the derived class. Thus, the obvious mitigation is to create an alias for the method in the base class. However, the long list of parameters the method takes is in flux as the derived class is being refined & retested. I'd like to avoid the boilerplate data entry task of re-typing the method signature, and alias it in a simpler manner, much like I can do with the 'using' directive for an inherited specialized constructor.
Simple example:
struct Person {
int ID;
void virtual sit() {};
void virtual walk() {};
void virtual run(int speed, int duration, int stride) {}; //method name in unambiguous in this scope
Person(int id) : ID(id) {} //specialized c'tor
};
struct Politician : Person {
void speak() {};
void campaign() {}; //use this to 'run' for office
//'sit' and 'walk' are clear enough, but 'run' is ambiguous in this scope, so alias it to 'sprint'
void sprint(int speed, int duration, int stride) {
Person::run(speed, duration, stride);
} //the above works, but is a boat-load of boilerplate that I'd like to avoid
using Person::Person; //use Person c'tor (avoids boilerplate)
//using sprint = Person::run; //doesn't work - "'run' in 'struct Person' does not name a type"
};
(Also consider a virtual class that inherits from multiple base classes, with one or more identically-named base-class methods. Such is my real-world application that I boiled down into this simpler example of the root need.)
Surely there is an easier way to create an alias for an unchanged inherited method, right?
The answer you asked for
template <typename ...T>
decltype(auto) wrapper(T... t)
{
return func_whos_sig_keeps_changing(t...);
}
The answer you need
You're either violating the primary principal behind inheritance, or have not yet thought through how you intend to use this.
The whole point of inhering from person is so that somewhere in your code you can have this:
std::unique_ptr<person> person_ptr;
...
...
person_ptr->run();
Without caring about what actual type of person it is.
If you can't do this with a politician, then its not a person and shouldn't inherit from person, at least not publicly.
Evidently the answer is: It cannot be done the easy (dynamic & elegant) way. It has to just be 'hard-coded' the way I showed as the example of how I wanted to avoid having to do it. This was proposed for the C++ standard and rejected because the need was "unlikely to become common enough to warrant a separate language feature," and "not likely to become everyday work for novices."
The proposed syntax to rename/alias an inherited method, adapted to my example, was:
void sprint() = Person::run;
Credit to SO users Max Lybbert and Tomalla for finding it in Design & Evolution of C++ section 12.8.
I am trying to implement a linked-list in C++. Currently, I have the following code:
using namespace std;
struct CarPart
{
int partNumber;
char partName[40];
double unitPrice;
CarPart* Next;
};
class ListOfParts
{
private:
int size;
CarPart* Head;
public:
ListOfParts():size(0), Head(NULL)
{
}
int Count()
{
return size;
}
};
Here the problem is, ideally, I should keep the Stuct CarPart within my Class. But I do not want to. At the same time, I don't want this to be acccessble anywhere from outside.
Can I have a some way, without creating a structure within the Class? Instead creating a new Class CarPart which could be accessible from only class ListOfPart?s
Well, as a first suggestion, have you considered using std::list? It would save you the trouble of implementing your own linked list semantics. Unless you're writing a linked list for the learning experience (which can be valuable), I suggest using:
struct CarPart
{
int partNumber;
std::string partName;
double unitPrice;
};
std::list<CarPart> ListOfParts;
You'll also notice I'm using std::string for text, which I suggest you use (unless you have a very good reason not to).
To the question at hand: you could declare the constructor for CarPart private, and then declare ListOfParts as a friend class, that's one way. But consider this: what do you gain by disallowing the construction of a car part external to the list of parts? I can't see that you gain anything. In fact, by using friends you introduce unnecessary complexity into the structure of your code - as using the dreaded 'friend' keyword usually does. Anyway, if you did want to use the friend class method, you would write:
class ListOfParts;
struct CarPart
{
friend class ListOfParts;
int partNumber;
char partName[40];
double unitPrice;
CarPart* Next;
private:
CarPart()
{
// Do nothing.
}
};
Which would mean only ListOfparts could call the default constructor for the list CarPart. Let me make this very clear: this is an abhorrent solution because it breaks rules of encapsulation. But, like mutable, friends have a use (and this isn't it).
What you're asking is contradictory. Either you want CarPart to be accessible from outside (in which case you declare it as a separate class or as a public member) or you don't want it accessible (in which case you declare it as a private member).
Consider making your class a little more generic: instead of having it be a linked list of CarParts, make it a class template that makes a linked list of Nodes that each has a T. If you are allowed to, you should be using std::list anyway, but you could write your own if you had to/really wanted to.
Also, classes and structs are basically the same thing; the only difference is that class members and inheritance are by default private, and struct members and inheritance are by default public. (The keywords are not always interchangeable, though.)
You can move your CarPart struct to a separate header and include this header only in the ListOfParts implementation part (yes, you need to separate definitions from implementations).
And don't forget a forward declaration
struct CarPart
before defining
class ListOfParts
Today I learned about the C++ "memberspace" idiom, which roughly abuses a property of C++ that makes T::bar as well as T.bar work, when T is both a type and an object in some scope.
struct A {
struct Controls {
/* put some typedefs/data/functions here */
} Controls;
};
// Can be used as a type and value
A a;
A::Controls::iterator it = a.Controls.begin();
Have you ever used this idiom in practice? Have you found it useful? What's some good or the best application of the idiom?
No, I have never used that technique (and I don't think it deserves to be called an "idiom"):
Since I haven't used it, I haven't found it useful.
A good application of that technique could be to confuse other programmers.
Another application could be to write a techno-babble article about how wonderful it is for some imagined never-in-practice encountered problem, perhaps obfuscated with lots of template metaprogramming?
Dunno, best application would probably be to write an article about all those silly-rules, like you can also have a struct and a function of the same name in the same scope, as I recall, and point out how anything that those can accomplish, can be accomplished much better by staying away from the darker corners of the language. :-) Articles don't pay much in moneys but they pay in respect and are fun to write. Please write it (TIA).
Cheers & hth.,
As #Steve already said in a comment, the fact that the nested type and the instance of this type have the same name is not a central aspect of this technique. To increase encapsulation, we could even use a member function to access the instance (even though it would less look like a namespace qualification). For example, the example you gave could be rewritten as follow without any drawback (well, maybe there are, but I can't find any at the moment):
struct A
{
struct Controls
{
//typedefs/data/functions
};
const Controls & getControls() { return controls_; }
private:
Controls controls_;
};
A a;
A::Controls::iterator = a.getControls().begin();
Here is how I see memberspaces. The goal of memberspaces is to divide the naming space of a class in order to group together related typedefs and methods. The Controls class above could be defined outside of A, but it is so tightly connected to A (each A is associated with a Controls, and vice-versa, a Controls is nothing more than a view on the object A in which it is contained) that it feels "natural" to make it a member of A, and possibly also make it friend with A (if there is a need to access A's internals).
So basically memberspaces let us define one or several views on a single object, without polluting the enclosing class namespace. As noted in the article, this can be quite interesting when you want to provide several ways to iterate over an object of your class.
For example, let's assume that I am writing a class for representing C++ classes; let's call it Class. A Class has a name, and the list of all its base classes. For convenience reasons, I would like a Class to also store the list of all the classes that inherit from it (its derived classes). So I would have a code like that:
class Class
{
string name_;
list< shared_ptr< Class > > baseClasses_;
list< shared_ptr< Class > > derivedClasses_;
};
Now, I need some member functions to add/remove base classes/derived classes:
class Class
{
public:
void addBaseClass( shared_ptr< Class > base );
void removeBaseClass( shared_ptr< Class > base );
void addDerivedClass( shared_ptr< Class > derived );
void removeDerivedClass( shared_ptr< Class > derived );
private:
//... same as before
};
And sometimes, I might need to add a way to iterate over base classes and derived classes:
class Class
{
public:
typedef list< shared_ptr< Class > >::const_iterator const_iterator;
const_iterator baseClassesBegin() const;
const_iterator baseClassesEnd() const;
const_iterator derivedClassesBegin() const;
const_iterator derivedClassesEnd() const;
//...same as before
};
The amount of names we are dealing with is still manageable, but what if we want to add reverse iteration? What if we change the underlying type for storing derived classes? That would add another bunch of typedefs. Moreover, you have probably noticed that the way we provide access to begin and end iterators does not follow the standard naming, which means we can't use generic algorithms relying on it (such as Boost.Range) without additional effort.
In fact, it is obvious when looking at the member functions name that we used a prefix/suffix to logically group them, things that we try to avoid now that we have namespaces. But since we can't have namespaces in classes, we need to use a trick.
Now, using memberspaces, we encapsulate all base-related and derived-related information in their own class, which not only let us group together related data/operations, but can also reduce code duplication: since the code for manipulating base classes and derived classes is the same, we can even use a single nested class:
class Class
{
struct ClassesContainer
{
typedef list< shared_ptr< Class > > const_iterator;
ClassesContainer( list< shared_ptr< Class > > & classes )
: classes_( classes )
{}
const_iterator begin() const { return classes_.begin(); }
const_iterator end() const { return classes_.end(); }
void add( shared_ptr< Class > someClass ) { classes_.push_back( someClass ); }
void remove( shared_ptr< Class > someClass ) { classes.erase( someClass ); }
private:
list< shared_ptr< Class > > & classes_;
};
public:
typedef ClassesContainer BaseClasses;
typedef ClassesContainer DerivedClasses;
// public member for simplicity; could be accessible through a function
BaseClasses baseClasses; // constructed with baseClasses_
DerivedClasses derivedClasses; // constructed with derivedClasses_
// ... same as before
};
Now I can do:
Class c;
Class::DerivedClasses::const_iterator = c.derivedClasses.begin();
boost::algorithm::find( c.derivedClasses, & c );
...
In this example, the nested class is not so coupled to Class, so it could be defined outside, but you could find examples with a stronger bound.
Well, after this long post, I notice that I did not really answer your question :). So no, I never actually used memberspaces in my code, but I think it has its applications.
I have considered it once or twice, notably when I was writing a facade class for a library: the facade was meant to make the library easier to use by having a single entry point, but as a consequence it had several member functions, which were all related, but with different degrees of "relatedness". Moreover, it represented a collection of objects, so it contained iteration-related typedefs and member functions in addition to "features-oriented" member functions. I considered using memberspaces to divide the class in logical "subspaces" in order to have a cleaner interface. Don't know why I haven't done it.
No, I've never used that.
A good use for it? Maybe you can use it to show your colleagues that you are better they are... just like some pleople use templates where they shoudn't, for a complex solution to a simple problem (note that templates, unlike memberspace idiom, sometimes are useful).
Any syntax flexibility is always welcomed regardless of whether is it is potentially confusing or not. In fact the trick is used in boost.array, this is a minimal implementation:
#include<cassert>
template<unsigned N>
struct fixed_array{ /* bla bla */
static unsigned size(){
return N;
}
};
int main(){
fixed_array<3> arr;
assert(arr.size() == 3); //like a stl container
assert(fixed_array<3>::size() == 3); //more proper, but less generic wrt stl containers
return 0;
}
so if the user wants to see a static member function/static member variable/nested class as a property of the instance and not the class then he/she can. Useful to write generic code for example, and it is not confusing at all in this example.
I have a nested class in c++ which has to be public. But I need some of its methods visible to the outer world, and the rest visible only to the nesting class. That is:
class set {
public:
class iterator {
innerMethod();
public:
outerMethod();
}
}
I want to be able to write a method for set which uses innerMethod(). If I make it public, I can access it from outside as well, which is something that I definitely don't want. Is there a way to do it without doing the "friend class set" thing?
Thanks in advance!
There is NO GOOD WAY you can do this, without using friend keyword.
In the comment you said:
In the programming class I currently
take, using 'friend' was said to be
ill-advised and generally considered
"bad programming" for the most part,
unless there is really no other way
around it. So I try to avoid it as
much as possible.
friend breaks encapsulation, maybe that is the reason why your class teacher said it's bad-programming. But member-functions too break encapsulation, then why do you use them? Why not avoid them too? friend breaks encapsulation in the same way as do member-functions; so if you're comfortable using member-functions when they're needed, then you should be comfortable using friend also when they're needed. Both exist in C++ for a reason!
class set {
public:
class iterator
{
friend class set; //<---- this gives your class set to access to inner methods!
void innerMethod(){}
public:
void outerMethod(){}
};
iterator it;
void fun()
{
it.innerMethod();
it.outerMethod();
}
};
See this : How Non-Member Functions Improve Encapsulation
No, I don't think there are other non-hacky methods but using the friend-directive.
friend exists right for this kind of purpose, why would you avoid it?
Try asking: is there any way to add 2 numbers without adding them?
Sorry if I'm harsh, but friend class is for exactly that...
Yes there is.
I've been trying to advocate the method for a while now, the basic idea is to use a Key class.
While this does not actually remove the use of friend, it does reduce the set of exposed implementations details.
class set;
// 1. Define the Key class
class set_key: noncopyable { friend class set; set_key() {} ~set_key() {} };
class set
{
// 2. Define the iterator
class iterator
{
public:
void public_method();
void restricted_method(set_key&);
}; // class iterator
}; // class set
Now, restricted_method is public, so set does not need any special access to iterator. However the use of it is restricted to those able to pass a set_key instance... and conveniently only set may build such an object.
Note that set may actually pass a set_key object to someone else it trusts. It is a key in the traditional sense: if you give a key of your flat to someone, it may entrust it to another person. However because of the semantics of the key class (non copyable, only set may construct and destroy it) this is normally limited to the duration of the scope of the key object.
Note that a evil hack is always possible, namely *((set_key*)0). This scheme protects from Murphy, not Machiavelli (it's impossible in C++ anyway).
You can do something like this:
class set
{
public:
class iterator
{
protected:
iterator(){};
virtual ~iterator(){};
public:
//outer world methods...
};
private:
class privateIterator : public iterator
{
public:
privateIterator(){};
~privateIterator(){}
//inner methods;
};
public:
iterator* CreateIterator()
{
return new privateIterator();//this is used to be sure that you only create private iterator instances
}
};
I don't know if it's the right answer, but it does now uses friend key work and it hides some of the methods. The only problem is that you can't declare privateIterator and you always must use CreateIterator to create an instance...
I'm having some toubt here. Hope you guys can share out some programming tips. Just curious to know whether is it a good programming practice if I do something like the code below.
class Outer {
public:
class Inner {
public:
Inner() {}
}
Outer() {}
};
I have been doing this for structure where I only want my structure to be expose to my class instead of global. But the case is different here, I am using a class now? Have you guys facing such a situation before? Very much appreciated on any advice from you ;)
I'll break the answer into two parts:
for cases where you only organize code, you should use namespaces instead of classes -- if the inner class isn't an entity that is only worked with from inside the class (especially only constructed in the class), then inner classes are a good idea -- another example STL function objects.
in C++ there is absolutely NO DIFFERENCE between structures and classes except that structures have public members by default. Hence there's no real difference when you have classes -- it's more a matter of style.
This is a good practice in many cases. Here's one where we implement a link list:
template <class T>
class MyLinkList {
public:
class Node {
public:
Node* next;
T data;
Node(const T& data, Node* node) : next(node), data(data) {}
};
class Iterator {
public:
Node* current;
Iterator(Node* node) : current(node) {}
T& operator*() { return current->data; }
void operator++(int) { current = current->next; }
bool operator!=(int) { return current != NULL; }
};
private:
Node* head;
}
The above is just snippet that is not intended to be complete or compilable. The point is to show that Node and Iterator are inner classes to the MyLinkList class. The reason why this makes sense is to convey the fact that Node and Iterator are not independent to be stand alone by themselves, but they need to be qualified by MyLinkList (for instance MyLinkList::Iterator it)
This is purely a matter of style, however I think it is typically more common in the C++ community to use a namespace named detail for classes that are purely helpers or are purely used in the implementation of other classes. There are several advantages to using namespaces in place of inner classes, among them include: greater compatibility (how compilers resolve names in inner classes can be incredibly different between Visual C++ and GCC, for example), more encapsulation (in the inner/outer variant, the inner class has greater access to members of instances of the outer class), easier implementation (you don't have to fully qualify the helper class every single time in the implementation file, since you can put a using directive in the ".cpp" source file). If you are going to use an inner class, then you need to make the conscious decision to make that a part of your API.
Using Namespaces
namespace collection
{
namespace detail
{
class LinkedListNode
{
//...
};
}
class LinkedList
{
// ...
};
}
Using Inner Classes
namespace collection
{
class LinkedList
{
// ...
class LinkedListNode
{
// ...
};
// ...
};
}
It's not an everyday thing, but it's not unheard of, either. You would do this if there were a class (Inner) that only makes sense to a client program when the client is using Outer.
If you only want a class to be exposed in a certain file, you can use an unnamed namespace within that file. Then whatever code is within that namespace is only available within that file.
namespace
{
//stuff
}