1. Replace define with Const,enum,inline as much as possible.
2. The old compiler may not allow static to get an initial value on its declaration. In addition, the so-called ' in-class ' initial setting may only be for integer constants, and if your compiler does not support the syntax above, you can put the initial value in the definition. If an array cannot be initialized, consider using the enumeration values in the class.
3. If the member variable is const or reference must be initialized with the initial value instead of using the assignment method.
4. Constructors are best used with member initialization lists rather than using assignment operations within the constructor body, and the member initialization list should have the same values listed in the class as they are declared.
5. To avoid the problem of initialization order across compilation units, replace the non-local static object with the local static object.
6. Any class that contains virtual functions is almost certain that there should be a virtual destructor.
7.string, and all STL containers, such as vector, list, set, etc. without virtual destructors.
8. Destructors never spit out an exception, and if a function called by a destructor might throw an exception, the destructor should be able to catch the exception and swallow the exception or end the program.
9. If the customer responds to an exception that is thrown during the operation of an action function, then class should provide a normal function instead of performing the operation in a destructor.
During the 10.base class function construction, the virtual function will never descend to the derived class class, and the object as if it is subordinate to the base type, the informal and the argument is that the virtual function is not a virtual function. The base class function is earlier than the derived class constructor, and the derived variable is not initialized when base is constructed. The same applies to destructors, once derived's destructor is executed, the derived member variable in the object renders an undefined value, and the destructor into base becomes a base class object, and any part of C + + includes the virtual function dynamic_ Casts would have seen it that way. A good practice is to put the common manifest code into an init function (not virtual), there may be problems, it is best not to call the virtual function in constructors and destructors.
11. Make the assignment operator return a reference to *this.
Handling self-assignment in operator: A low-level method-self-replicating checks. Advanced Method-Saves the copy.
The 12.Copying function should ensure that all member variables within the assigned object and the composition of the base class. Instead of trying to initialize another copying constructor with one copying constructor, you should place the common skills in the third function.
13. Store the Newed object with a smart pointer in a separate statement. If you do not, once an exception is thrown, it is possible to cause an imperceptible resource leak.
14. Never return to pointer or reference point to a local stack object, or to a Heap-allocate object before returning (perhaps no one has delete it)
15. A pure virtual function in a class can define its own implementation, but this can be done through a derived class object or a pointer to a derived class to display the calling
Class A
{
Public
virtual void fun1 () = 0;
};
void A::fun1 ()
{
cout << "void A::fun1 ()" << Endl;
}
Class B:public A
{
Public
virtual void fun1 ()
{
cout << "void B::fun1 ()" << Endl;
A::FUN1 ();//This can also
}
};
int _tmain (int argc, _tchar* argv[])
{
A *q = new A;
Q->fun1 (); Error
A *p = new B;
P->fun1 ();
P->a::fun1 ();
System ("pause");
return 0;
}
The name within the
16.derived class obscures the name within the base class. Pointing to a derived class by a base class pointer prevents the name from being masked and cannot be called correctly, but is actually exploited by polymorphism.
Class A
{
Public:
virtual void fun1 () = 0;
virtual void fun1 (int n)
{
cout << "void a::fun1 (int n)" << Endl;
}
virtual void fun2 ()
{
cout << "void a::fun2 ()" << Endl;
}
void Fun3 ()
{
cout < < "void A::fun3 ()" << Endl;
}
void fun3 (int n)
{
cout << "void a::fun3 (int n)" << Endl;
}
};
Class B:public A
{
Public:
virtual void fun1 ()
{
; cout << "void B::fun1 ()" << Endl;
}
void Fun3 ()
{
cout < < "void B::fun3 ()" << Endl;
}
void Fun4 ()
{
cout < < "void B::fun4 ()" << Endl;
}
};
int _tmain (int argc, _tchar* argv[])
{
b b;
int n = 250;
B.fun1 ();
B.FUN1 (n); Error, scope is overwritten must show call B. A::FUN1 (N)
B.fun2 ();
B.fun3 ();
B.FUN3 (n); Error, scope is overwritten must show call B. A::FUN3 (N)
B *p;
int n = 250;
P->fun1 ();
P->FUN1 (n); Error, scope overridden must show call P->A::FUN1 (n)
P->fun2 ();
P->fun3 ();
P->FUN3 (n); Error, scope overridden must show call P->A::FUN3 (n)
Pointing to a derived class by a base class pointer prevents the name from being masked and cannot be called correctly, but is actually exploited by polymorphic
A *a = new B;
int n = 250;
A->fun1 ();
A->FUN1 (n);
A->fun2 ();
A->fun3 ();
A->FUN3 (n);
b *p = new B;
P->fun1 ();
P->FUN1 (5); Error, the derived class overrides the name of the base class after overriding the names of the bases, cannot call the base class's fun1 (int n), and can call the base class's object function if it is not overridden
P->fun2 ();
P->fun3 ();
P->FUN3 (6);//error, a derived class overrides the name of the base class after overriding the names of the bases, cannot call the base class's fun1 (int n), and can call the base class's object function if it is not overridden
P->fun4 ();
System ("pause");
return 0;
}
The Non-virtual function A::fun3 and b::fun3 are both statically bound, the consciousness is that Q is declared as Pointer-to-a, and the Non-virtual function called by P is always the version defined by a, even if q points to the
A derived class object of type A. On the other hand, virtual functions are dynamically bound, so they are not subject to this problem, and if FUN3 is a virtual function, either p or Q calls FUN3, it will cause the call
B::fun3, because they really mean an object of type B.
Then the above Class A, B
b *p = new B;
P->fun3 (); The fun3 of B is called.
A *q = new B;
Q->fun3 (); The fun3 of a is called.
18. Please do not redefine an inherited non-virtual function, if you need to do so, should initially consider design as a virtual function
19. Never redefine the inherited default parameter values, the virtual function is dynamic binding, when invoking a virtual function, which part of the function implementation code is called, depending on the type of the object that called the Ding Tai,
The default parameter value is a static binding, and the static bound function does not inherit the default function value from its base.
20. Pass parameters in By-reference to avoid object cutting problems when a derived class is passed by-value and treated as a base class object, the copy constructor of the base class
will be called, and what characteristic properties of this object like a derived class object will be completely cut off, leaving only a base class object. The solution to the cutting problem is to By-reference-const
The way to pass parameters, in the C + + compiler underlying reference is often implemented with pointers, as far as possible to replace the Pass-by-value, the former is usually more efficient, and can avoid cutting problems
However, for built-in types and STL iterators and function objects, it is appropriate to use Pass-by-value
Class A
{
Public
A ()
{
cout << "a::a ()" << Endl;
}
A (const a &refs)
{
cout << "a::a (const A &refs)" << Endl;
}
};
Class B:public A
{
Public
B (): A ()
{
cout << "b::b ()" << Endl;
}
B (const b &refs): A (refs)
{
cout << "b::b (const B &refs)" << Endl;
}
void Fun2 ()
{
cout << "b::fun2 ()" << Endl;
}
};
void Fun (A a)
{
A.fun2 ();//error cannot be called
}
int _tmain (int argc, _tchar* argv[])
{
B obj;
(obj);//The copy constructor constructor for a is called instead of B, and no object of B is generated
System ("pause");
return 0;
}
21. If you need to type-convert all the parameters of a function (including the implied this parameter), then this function must be non-member
22. Postpone the occurrence of variable definitions as much as possible. This can increase the clarity of the program and improve the efficiency of the program.
23. If possible, avoid dynamic_cast in transition, especially in code that focuses on efficiency. If you have a design that requires transformational action, try to develop an alternative design that doesn't need to be transformed. If the transition is necessary,
Try to hide it behind a function in the field. The client then calls this function without having to put the transformation into their own code.
24. The nature of the minimization of compilation dependencies: In reality, make the head file as self-sufficient as possible, in case you do not, then he and other documents in the declaration (rather than the definition of the formula) dependent.
If you use Object-reference or object pointers to complete the task, do not use objects.
Replace the definition with the class declaration as much as possible.
Define different files for the declaration and definition.
Some places to watch out for