Examine the following code:
classabstractbase{ Public: VirtualIBase () =0; VirtualInterface ()Const=0; Virtual Const Char*Member ()Const{return_member;} protected: Char*_member;}
There is a problem with this code, although the class is abstract, but it still needs a constructor to initialize the _member.
It may be felt that the Abstractbase designer tried to give each of its derived classes the initial value of _member. But if so, the only requirement for derived class is that abstractbase must provide a protected constructor with a unique parameter:
abstractbase::abstractbase (char0) : _member (member_value) {}
In general, the data member of class should be initialized and only specify the initial value in constructor or in class member functions. Any other operation will break the encapsulation nature, making the class maintenance and modification more difficult.
Of course, you may also say that the designer's mistake is not to provide a explicit constructor but rather he should not declare the data members in an abstract base class. The idea of an interface is certainly true, but it is also justified to put the shared data in base class.
Novice C + + (like me) is often surprised to find that a person can define and invoke a pure virtual function; However, they can only be called statically, not through virtual mechanisms. For example, the following code is valid:
voidconst{ // pre-defined pure virtual function Interface () constvoid conceretederived::interfaceconst{ // Call a pure virtual function abstractbase::interface ();}
Specifically, it depends on the designer of class. The only exception is pure virtual destructor; The designer of class must define it. Because each derived class destructor is extended by the compiler, calls each of its virtual base ckass and the destructor of the previous base class in a static invocation. So as long as one is missing, it causes the link to fail.
PS. I use the VC + + 12.0 compiler to display:
Error LNK2019: unresolved external symbol "Public:virtual void __thiscall
and fatal error lnk1120:1 an unresolved external command;
The error displayed on GCC 4.8.1 is:
Undefined reference to ' ibase::interface () const '
This one... I am looking forward to using Clang or ICC friends to compile this code to see if I can succeed ...
But paragraph code Lippman said is legal, I would like to believe it.
One might think that the invocation of a pure virtual destructor should not be suppressed when the compiler expands derived class destructor? No, the class designer may have really defined a pure virtual destructor, which is a guarantee of the C + + language: The destructor of every class object in the integration system will be called, so the compiler does not Can suppress this operation.
You may also think that the compiler will not synthesize a pure virtual destructor function definition? Unfortunately the compiler is not good, because it is a separate compilation model for an executable file, the development environment can provide a device, when linking to find the pure virtual destructor entity, and then reactivate the compiler, give a special instruction, Of course, whether there is a compiler really do not know.
The existence of virtual specifications
If we really design abstractbase::member () as a virtual function, it would be a bad choice because its function definition is not related to the type, so it will not be rewritten by the successor derived class. In addition, because its non-virtual function entity is an inline function, if it is often called, the efficiency of retribution is not light.
So can the compiler parse out that the function actually has only one entity in the class hierarchy? If so, can you convert the call operation to a static call operation to allow the inline expansion of the call operation? What if the class hierarchy is added to the new classes and the new entity with this function? Yes, the new class will spoil the optimization! The function is recompiled (or the second entity is generated, and the compiler determines which one is called). However, to dig out such dependencies, it is possible to need some form of persistent program database or Libray manager.
So it's not a good idea to declare all the member functions as virtual function and then remove the nonessential virtual invocation by the compiler's optimizations.
The existence of const in virtual specification
Deciding whether a virtual function requires a const seems like a trivial matter, but when you really think about it, it's not easy to make a decision. Doing this means assuming that the subclass entity may be used infinitely, not declaring the function as const, and that the function cannot get a const reference or const pointer. More disgusting, after declaring a function as const Only to realize that its derived instance must modify a data member ...
So the advice is to not add a const to virtual function.
Conclusion:
A reliable class is a guarantee to avoid headaches:
classabstractbase{ Public: Virtual~abstractbase () =default; Virtual voidInterface () =0; Const Char* Member ()Const{return_member;}//just one entity. What do you learn from others?protected: Abstractbase (Char*member =0): _member () {}//a constructor with parameters Char*_member;};
Existence of pure virtual function & virtual specification, and the existence of const