Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - What's the point of nested classes?

I'm studying a little of C++ and now I'm fighting against it's similitudes with Java. I know the purpose of inner classes in Java, but now I'm trying to use nested classes in C++, and I discover that private attributes of "container" class are not visibile by nested class, so why I should use them? Also, is there a way to make visibile those attributes?

like image 327
Leo91 Avatar asked Jul 09 '15 07:07

Leo91


People also ask

What is the point of a nested class?

As mentioned in the section Nested Classes, nested classes enable you to logically group classes that are only used in one place, increase the use of encapsulation, and create more readable and maintainable code.

Is it good practice to use nested classes?

Nested Class can be used whenever you want to create more than once instance of the class or whenever you want to make that type more available. Nested Class increases the encapsulations as well as it will lead to more readable and maintainable code.

What is the purpose of nested classes C++?

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.

What are the advantages disadvantages of nested classes?

And the benefit of it is you can have less number of objects created at runtime which wouldn't be the case with other types of nested classes. Disadvantage The only disadvantage I can think of is a static nested class has access to both the protected and private members of the outer class.


2 Answers

I'm studying a little of C++ and now I'm fighting against it's similitudes with Java.

First of all be aware that C++ nested classes are similar to what in Java you call static nested classes. There isn't anything in C++ syntax to reproduce Java nested classes.

I discover that private attributes of "container" class are not visible by inner class...

C++ 98

In C++ inner classes aren't different to normal classes, they're not class members then they can't access container class' private members (unlike other languages like Java or C#).

C++ 03

Nested classes are class members but restrictions on what they can access still applies (see also section Weird things at the end of this answer). It has been considered a standard defect (see DR45) then some compilers earlier implemented C++0x access rule earlier even when compiling for C++03 (notably GCC, thanks to Jonathan Wakely to spot this out).

C++ 11

This rule changed in C++ 11, now nested classes can access private member of container class. From §11.7:

A nested class is a member and as such has the same access rights as any other member.

Of course you still need an instance to access non static members.


...so why I should use them?

They're then an implementation detail to group related classes and they have same issues about their usage that you may have in other languages (clarity for newbies, primary). Their greatest benefit IMO is encapsulation, if for example you have this:

class stream {     virtual void write(const std::string text) = 0; };  class channel { public:     virtual stream* get_stream() = 0;      // Other methods... };  class tcp_channel : public channel { public:     virtual stream* get_stream() {         return new tcp_stream(this);     }  private:     class tcp_stream : public stream { /* implementation */ }; }; 

They're also helpful in some circumstances to substitute nested namespaces:

class protocol { public:     virtual void create_connection() = 0;      class tcp : public protocol { /* implementation */ };     class shared_memory : public protocol { /* implementation */ };     class named_pipes: public protocol { /* implementation */ }; };  auto media = protocol::tcp(); 

Or to hide implementation details:

class file_system_entry { public:     class file : public file_system_entry { };     class directory : public file_system_entry { };      std::time_t get_last_modified() { ... }      void remove() { ... }     virtual void copy_to(std::string path) = 0;  private:     class local_handle {         // Implementation details     } _handle; }; 

There are many others usage patterns (see also Why would one use nested classes in C++? for a much better discussion), just remember not everyone will correctly understand (and use!) them. See also Pros and cons of using nested C++ classes and enumerations?

Also, is there a way to make visible those attributes?

Before C++ 11 you can't (of course unless you declare them as friends but see next paragraph), if you need this feature just use a C++ 11 compiler (that supports this feature). GCC does (from long time ago) and also MSVC does, I don't know about other compilers.

Nested Friends

Is there any difference between C++ 11 access rules and friend classes? In general they're almost equivalent (automatic access is just less verbose):

class container { public:     class nested;     friend class nested;      class nested { }; }; 

Compared to:

class container { public:     class nested { }; }; 

However with forward declaration you have some side effects. Also remember that from accessibility point of view they're equivalent (access, like friendship, is not inherited nor transitive). These examples don't compile:

class external : public container::nested { public:     // No: only class declared inside "container"     // has access to private members, we do not inherit that      void foo(container obj) { /* access a private member of obj*/ } };  // No, "container" has not access to "nested" private members, // visibility isn't reciprocal void container::foo(container::nested obj) {     // Access some private member of obj }  // No, we don't have anything to do with container, // visibility isn't transitive void friendOfNested(container obj) {     // Access some private member of obj } 

Are then completely equivalent? No, because private members of container's friends are accessible in nested if it's a nested class in C++ 11 but they're not if nested is a friend of container. Given this outlined structure:

class container;  class another {     friend class container;      };  class container { public:     class nested { };    }; 

nested can access another's private members:

void container::nested::foo(another obj) {     obj.somePrivateMember = 0; } 

It works because nested is a member of container then transitive restriction of friendship doesn't apply. Before C++ 11, declaring nested as friend of container, that code won't compile because friendship isn't transitive.

Weird things

We'd assume we can always declare a nested class as friend of its container? Actually standard said (SO/IEC 14822:2003(E), 11.8):

A friend of a class is a function or class that is not a member of the class...

Then we shouldn't be able to declare nested as friend of container: in C++ 03 nested classes are class members (but standard explicitly said they have no access to container privates and also they can't be friends of container class). It seems there was no hope, fortunately most compilers allowed us to do so (regardless to what standard said).

like image 50
Adriano Repetti Avatar answered Oct 16 '22 16:10

Adriano Repetti


It provides another good encapsulation technique. Placing one class entirely within the namespace of another class reduces its visibility to other parts of your code base. This helps achieve scalability and reduces your maintenance burden.

Function objects are often coded in such a manner.

like image 42
Bathsheba Avatar answered Oct 16 '22 16:10

Bathsheba