面向对象编程基于三个基本概念:数据抽象、继承和动态绑定。
在C++中,用类进行数据抽象,用类派生从一个类继承另一个类:派生类继承基类的成员。
动态绑定使编译器能够在运行时决定是使用基类中定义的函数还是派生类中定义的函数。
1.多态性仅用于通过继承而相关联的类型的【引用或指针】;
2.通过基类的【引用或指针】调用【虚函数】时,发生动态绑定。引用或指针既可以指向基类对象也可以指向派生类对象,调用的虚函数在运行时确定,被调用函数是引用或指针所指对象的实际类型所定义的;
2.除了构造函数之外,任意非static成员函数都可以是虚函数(继承层次的根类一般都要定义虚析构函数);
3.保留字virtual只在类内部的成员函数声明中出现;
4.派生类对基类的public和private成员的访问权限与程序中任意其他部分一样:它可以访问public成员而不能访问private成员;
5.protected成员可以被派生类对象访问,但不能被该类型的普通用户访问;
派生类只能通过派生类【对象】访问其基类的protected成员;
派生类对其基类类型对象的protected成员没有特殊访问权限;
以下是一个例子,派生类Bulk_item需要通过派生类对象d访问price,但不可以直接访问基类类型对象b的price成员:
void Bulk_item::memfcn(const Bulk_item &d, const Item_base &b)
{
double ret = price; //ok,uses this->price;
ret = d.price; //ok,uses price from a Bulk_item 【object】
ret = b.price; //error
}
6.一般情况下,派生类中虚函数的声明必须与基类中的定义方式完全匹配,一个例外:返回对基类型的引用或指针的虚函数,派生类中可以返回基类函数所返回类型的派生类的引用或指针;
7.已定义的类才可以用作基类;
8.如果需要声明(但并不实现)一个派生类,则声明包含类名但不包含派生列表:
class Bulk_item: public Item_base; //error
class Bulk_item; //ok
9.要触发动态绑定,必须满足两个条件:
a.只有指定为虚函数的成员函数才能进行动态绑定;
b.必须通过基类类型的引用或指针进行函数调用;
10.派生类到基类的转换:
double print_total(const Item_base&, size_t);
Item_base item;
print_total(item, 10);
Bulk_item bulk;
print_total(bulk, 10); //ok,使用bulk中的Item_base部分
//无论实际对象具有哪种类型,编译器都将它当做基类类型对象
11.动态绑定的关键:对象的实际类型(动态类型)可能不同于该对象引用或指针的静态类型;
通过引用或指针调用虚函数时,在运行时才确定调用哪个函数,被调用的是与动态类型相对于的函数:
Quote base("0-201-82470-1", 50);
print_total(cout, base, 10); // calls Quote::net_price
Bulk_quote derived("0-201-82470-1", 50, 5, .19);
print_total(cout, derived, 10); // calls Bulk_quote::net_price
**如果调用非虚函数,则无论实际对象是什么类型,都执行基类类型所定义的函数(即使,Bulk_item定义了自己的book函数版本,该函数为非虚函数,因此调用也会调用【基类】中的版本);
**对象是非多态的,也就是,当不是通过引用和指针来调用时,运行的函数(虚函数或非虚函数)都是由对象的类型定义的。
12.我们可以通过作用域操作符显式调用我们想要的虚函数版本;
13.
共有继承:基类的public成员为派生类的public成员,基类的protected成员为派生类的protected成员;
受保护继承:基类的public和protected成员在派生类中为protected成员;
私有继承:基类的public和protected成员在派生类中为private成员;
14.个别成员的访问控制:
派生类可以【恢复】继承成员的访问级别,但不能使访问级别比基类中原来指定的更严格或更宽松:
class Base {
public:
std::size_t size() const { return n; }
protected:
std::size_t n;
};
class Derived : private Base { // note: private inheritance
public:
// maintain access levels for members related to the size of the object
using Base::size;
protected:
using Base::n;
};
15.默认继承保护级别
class默认具有private继承,struct默认具有public继承:
class Base { /* ... */ };
struct D1 : Base { /* ... */ }; // public inheritance by default
class D2 : Base { /* ... */ }; // private inheritance by default
16.友元可以访问类的private和protected数据,【友元关系不能继承】;
17.如果基类定义了static成员,则整个继承层次中只有一个这样的成员,即每个static成员只有一个实例;static成员遵循常规的访问控制,当可以访问时,可以使用作用域操作符也可以使用点或箭头成员访问操作符来访问。