26. Beware of potential two semantics.
Some examples of potential two semantics:
Class A{public:a (const b&);}; Class B{public:operator A () const;}; void f (const a&);
In general, this will not be an error, but when the F function is called to pass in a B's object B, a two semantic error occurs, B can either get an object of a through the constructor of a, or use B's type conversion operator to turn B into an object of a, and the compiler does not know which method to use. This is a potential two semantics, which normally is normal and correct.
There is also a simpler two semantics, when two function overloads, such as f (int) f (char), and when passed in a double type parameter d, will occur two semantics, the compiler does not know whether to convert D to char type or int type.
Multiple inheritance is full of the possibility of two semantics. If more than one base class has a function or data member with the same name, it is necessary to indicate the base class of the member to eliminate ambiguity, even if some members are private in the base class in which the derived class is inaccessible, but there is a two semantic error. Why removing the ambiguity of a reference to a class member does not take into account access: Changing the access rights of a class member should not change the meaning of the program, that is, when a class is defined, changing the access properties of a member can cause some access errors or is still normal, which is correct, and if changing the access property alters the meaning of the program ( Class B derives from Class C, in C, a function calls a member of the same name in two base classes, if the ambiguity is eliminated, if access is considered, when the member in A is public and B is private, the function in C invokes the member in a, and the access is changed, the private in a, and the common in B, causes the function in C to call the member in B. Change the meaning of the program, but for the program ape, but do not know. If the protection is considered, there will be an access error, prompting the programmer to modify it, so it is best to display the ambiguity.
27. If you do not want to use an implicitly generated function, explicitly prohibit it.
For those functions that you do not want to use, the reason is simple, in order to be easier to update and maintain later, when you are now writing this class, you do not prohibit these should not use the function, you remember these things, so you do not make these mistakes, but after a long time, Or if someone else takes over your work to upgrade and maintain your code, this non-banned feature is likely to be in some places that you're unprepared for. Therefore, it is best to disallow these functions that should not be used.
For some functions in a class, the compiler implicitly generates automatically, such as the default parameterless constructor, assignment =, copy constructor, and so on, a simple way to suppress these functions is to declare these functions private, and the display declaration to prevent the compiler from automatically generating, while private prevents others from invoking it.
However, this is still unsafe, and member functions and friend functions can still call these private functions. This will only declare these functions, without defining the function body, and when other functions are called, the compiler will be wrong in the link times.
28. Divide the global namespace.
Use namespaces to resolve naming conflicts. There have been some studies before namespaces: C + + namespaces, namespaces can be nested.
Namespaces are used in three ways, using namespace xxx, after which all members of the XXX namespace can be accessed directly. Using XXX:: Member, for this member of the XXX namespace can be used directly. XXX:: Member, in one place use this member of the XXX namespace.
You can use structs to approximate namespace, create a structure to hold the global symbol names, and then place the global symbol names as static members into the structure. Access is prefixed with a struct's name, similar to a namespace.
struct Sdm{static const double VERSION, Class a{public:void F () {cout<< "SDM" <<endl;}};}; Const double sdm::version = 1.0;class a{public:void f () {cout<< "Globel" <<endl;}}; int main () {cout<<sdm::version;sdm::a SDMA; A;
For type names, you can explicitly remove a spatial reference:
typedef SDM::A A;
For a function, typically returns a constant pointer to a function:
sdm::a& (* const geta) () = sdm::geta;sdm::a& (& geta) () = sdm::geta;//Returns a reference to a function
Effective C + + 26,27,28