| Start | ||||||||
|---|---|---|---|---|---|---|---|---|
| Class basics A class is a user-defined type. A class is introduced with the A class is a collection of class members, which can be:
The For example, the following code snippets are identical: By declaring a class` a new type is added to your program, and it is possible to instantiate objects of that class by Members of a class are accessed using dot-syntax. |
||||||||
| Final classes and structs Deriving a class may be forbidden with Now any attempt to subclass it will cause a compilation error: Final class may appear anywhere in class hierarchy: |
||||||||
| Access specifiers There are three keywords (opens new window) that act as access specifiers. These limit the access to class members following the specifier, until another specifier changes the access level again:
When the type is defined using the Access specifiers are mostly used to limit access to internal fields and methods, and force the programmer to use a specific interface, for example to force use of getters and setters instead of referencing a variable directly: Using Note that the The |
||||||||
| Inheritance Classes/structs can have inheritance relations. If a class/struct There are 3 forms of inheritance for a class/struct:
Note that the default inheritance is the same as the default visibility of members: It's even possible to have a
Note that although When OOP was relatively new, (public) inheritance was frequently said to model an "IS-A" relationship. That is, public inheritance is correct only if an instance of the derived class is also an instance of the base class. This was later refined into the Liskov Substitution Principle (opens new window): public inheritance should only be used when/if an instance of the derived class can be substituted for an instance of the base class under any possible circumstance (and still make sense). Private inheritance is typically said to embody a completely different relationship: "is implemented in terms of" (sometimes called a "HAS-A" relationship). For example, a Protected inheritance is almost never used, and there's no general agreement on what sort of relationship it embodies. |
||||||||
| Friendship The |
||||||||
| Virtual Inheritance When using inheritance, you can specify the When class If we un-comment Also note that when we're creating variable It is useful when solving the diamond problem (opens new window).:
Virtual inheritance solves this problem: Since virtual base resides only in most derived object, there will be only one instance of Removing the comments resolves the ambiguity. |
||||||||
| Accessing class members To access member variables and member functions of an object of a class, the When accessing the members of a class via a pointer, the When accessing static class members, the BackgroundThe One would expect that The uncommonly used solution to this problem would be to explicitly control the precedence: Instead, the The |
||||||||
| Private inheritance: restricting base class interface Private inheritance is useful when it is required to restrict the public interface of the class: This approach efficiently prevents an access to the A public methods by casting to the A pointer or reference: In the case of public inheritance such casting will provide access to all the A public methods despite on alternative ways to prevent this in derived B, like hiding: or private using: then for both cases it is possible: |
||||||||
| Nested Classes/Structures A From outside of the enclosing class, nested classes are accessed using the scope operator. From inside the enclosing class, however, nested classes can be used without qualifiers: As with a non-nested As with non-nested classes, nested classes can be forward declared and defined later, provided they are defined before being used directly. Prior to C++11, nested classes only had access to type names, As of C++11, nested classes, and members thereof, are treated as if they were Conversely, the enclosing class is not treated as a friend of the nested class, and thus cannot access its private members without explicitly being granted permission. Friends of a nested class are not automatically considered friends of the enclosing class; if they need to be friends of the enclosing class as well, this must be declared separately. Conversely, as the enclosing class is not automatically considered a friend of the nested class, neither will friends of the enclosing class be considered friends of the nested class. As with all other class members, nested classes can only be named from outside the class if they have public access. However, you are allowed to access them regardless of access modifier, as long as you don't explicitly name them. You can also create a type alias for a nested class. If a type alias is contained in the enclosing class, the nested type and the type alias can have different access modifiers. If the type alias is outside the enclosing class, it requires that either the nested class, or a As with other classes, nested classes can both derive from or be derived from by other classes. This can be useful in situations where the enclosing class is derived from by another class, by allowing the programmer to update the nested class as necessary. This can be combined with a typedef to provide a consistent name for each enclosing class' nested class: In the above case, both |
||||||||
| Member Types and Aliases A Like static members, these typedefs are accessed using the scope operator, As with normal type aliases, each member type alias is allowed to refer to any type defined or aliased before, but not after, its definition. Likewise, a typedef outside the class definition can refer to any accessible typedefs within the class definition, provided it comes after the class definition. Member type aliases can be declared with any access level, and will respect the appropriate access modifier. This can be used to provide a level of abstraction, allowing a class' designer to change its internal workings without breaking code that relies on it. In this situation, if the helper class is changed from This can also be combined with In this situation, changing the implementation of As with everything, however, this can be taken too far. If the typename is only used once or twice internally and zero times externally, for example, there's no need to provide an alias for it. If it's used hundreds or thousands of times throughout a project, or if it has a long enough name, then it can be useful to provide it as a typedef instead of always using it in absolute terms. One must balance forwards compatibility and convenience with the amount of unnecessary noise created. This can also be used with template classes, to provide access to the template parameters from outside the class. This is commonly used with containers, which will usually provide their element type, and other helper types, as member type aliases. Most of the containers in the C++ standard library, for example, provide the following 12 helper types, along with any other special types they might need. Prior to C++11, it was also commonly used to provide a "template This was often used with types with multiple template parameters, to provide an alias that defines one or more of the parameters. |
||||||||
| Multiple Inheritance Aside from single inheritance: You can also have multiple inheritance:
Note: this can lead to ambiguity if the same names are used in multiple inherited *Ambiguity in Multiple Inheritance * Multiple inheritance may be helpful in certain cases but, sometimes odd sort of problem encounters while using multiple inheritance. For example: Two base classes have functions with same name which is not overridden in derived class and if you write code to access that function using object of derived class, compiler shows error because, it cannot determine which function to call. Here is a code for this type of ambiguity in multiple inheritance. But, this problem can be solved using scope resolution function to specify which function to class either base1 or base2: |
||||||||
| Static class members A class is also allowed to have Static member variables are not considered to be defined inside the class, only declared, and thus have their definition outside the class definition; the programmer is allowed, but not required, to initialise static variables in their definition. When defining the member variables, the keyword Due to this, static variables can be incomplete types (apart from Static member functions can be defined inside or outside the class definition, as with normal member functions. As with static member variables, the keyword If a static member variable is declared As of C++11, static member variables of If a As static members aren't tied to a given instance, they can be accessed using the scope operator, They can also be accessed as if they were normal, non-static members. This is of historical significance, but is used less commonly than the scope operator to prevent confusion over whether a member is static or non-static. Class members are able to access static members without qualifying their scope, as with non-static class members. They cannot be Static members respect access modifiers, just like non-static members. As they aren't tied to a given instance, static member functions have no Due to not having a Due to not having a As they aren't tied to a given instance, static member variables are effectively treated as special global variables; they're created when the program starts, and destroyed when it exits, regardless of whether any instances of the class actually exist. Only a single copy of each static member variable exists (unless the variable is declared Static member variables have the same linkage as the class, whether the class has external or internal linkage. Local classes and unnamed classes aren't allowed to have static members. |
||||||||
| Non-static member functions A class can have non-static member functions (opens new window), which operate on individual instances of the class. These functions are called on an instance of the class, like so: They can be defined either inside or outside the class definition; if defined outside, they are specified as being in the class' scope. They can be CV-qualified (opens new window) and/or ref-qualified (opens new window), affecting how they see the instance they're called upon; the function will see the instance as having the specified cv-qualifier(s), if any. Which version is called will be based on the instance's cv-qualifiers. If there is no version with the same cv-qualifiers as the instance, then a more-cv-qualified version will be called if available. Member function ref-qualifiers indicate whether or not the function is intended to be called on rvalue instances, and use the same syntax as function cv-qualifiers. CV-qualifiers and ref-qualifiers can also be combined if necessary. They can also be virtual (opens new window); this is fundamental to polymorphism, and allows a child class(es) to provide the same interface as the parent class, while supplying their own functionality. For more information, see here (opens new window). |
||||||||
| Unnamed struct/class Unnamed or and later but NOT anonymous Note: Some compilers allow anonymous Syntax
RemarksNote that the only difference between the |
Read Article
https://develop.horje.com/learn/1434/reference