Enssential C++ Chap5 面向对象
1.
The two primary characteristics of object-oriented programming are inheritance and
polymorphism. Inheritance allows us to group classes into families of related types, allowing for
the sharing of common operations and data. Polymorphism allows us to program these families as
a unit rather than as individual classes, giving us greater flexibility in adding or removing any
particular class.
这段话开宗明义,指明面向对象的核心是继承和多态,继承支撑代码重用,多态允许我们对一类对象进行编程,省去
分别处理的麻烦。
2.
首先对看过我这篇文章的人致以歉意,因为写了第一条以后,琐事缠身,相隔两天才来补充后面的内容。
闲话休提,只谈技术。
创建虚基类三部曲:
1)The first step in defining an abstract base class is to identify the set of operations common to its
children.
2)The next step in the design of an abstract base class is to identify which operations are type-
dependent — that is, which operations require separate implementations based on the derived
class type.
//基于显而易见的原因,静态成员函数不能是虚函数。
3)The third step in designing an abstract base class is to identify the access level of each operation.
有的函数在虚基类中可能不需要实现,那么就设计成纯虚函数:
virtual void gen_elems(int pos) = 0;
析构函数必须是虚函数。
3.
By qualifying the call of a virtual function with the class scope operator, we are telling the compiler which
instance to invoke. The run-time virtual mechanism is overridden.
通过加上被调用函数的类,可以覆盖动态绑定机制。例:
ostream& Fibonacci:: print(ostream &os) const { int elem_pos = _beg_pos-1; int end_pos = elem_pos + _length; if (end_pos > _elems.size()) Fibonacci::gen_elems(end_pos); //Fibonacci 的父类中也有gen_elems, 并且是虚函数 while (elem_pos < end_pos) os << _elems[elem_pos++] << ' '; return os; }
4.
If we choose to override the base class instance, the prototype of the derived class instance must
match the base class protoype exactly: the parameter list and the return type and whether the
virtual function is const or non-const. For example, the following definition of
Fibonacci::what_am_i() is not quite right:
class Fibonacci : public num_sequence {
public:
virtual const char* what_am_i() // not quite right ...
{ return "Fibonacci"; }
// ...
};
包括const 哟
5.
There are two circumstances under which the virtual mechanism does not behave as we expect: (1)
within the base class constructor and destructor and (2) when we use a base class object rather
than a base class pointer or reference.
6
An alternative implementation is to use the typeid operator. The typeid operator is part of the
run-time type identification (RTTI) language support. It allows us to ask a polymorphic class
pointer or reference the actual type of the object it refers to.
#include <typeinfo>
inline const char* num_sequence::
what_am_i() const
{ return typeid(*this).name(); }
A static_cast is potentially dangerous because the compiler does not confirm that our
conversion is correct. This is why I've couched its use in the truth condition of the typeid
operator. A conditional conversion is provided by the dynamic_cast operator:
if (Fibonacci *pf = dynamic_cast<Fibonacci*>(ps))
pf->gen_elems(64);