组合
定义:将一个类的对象作为另一个类的成员。
嵌入对象为公有成员:既可以使用新类接口提供的功能,还可以向包含的对象发送消息;
嵌入对象为私有成员:新类中的方法可以使用成员对象提供的功能,新类包含的成员对象被隐藏。
对象成员的初始化:
在创建一个包含对象成员的组合对象是,会执行成员类的构造函数初始化对象成员。成员对象的初始化使用初始化列表语法。如果没有在初始化列表中对成员对象进行显示初始化,编译器会执行成员对象默认的构造函数。
class M{
int x;
public:
M(int v):x(v){}
};
class W{
int y;
M m;
public:
w(int a,int b):y(a),m(b);{}
};
继承
类的继承的原理是讲一个类作为基类,它被继承,继承得到的新类称为派生类派生类也可以被再次继承。
继承关系的语法形式
class 派生类名:基类名表
{ 数据成员和数据成员函数声明
};
派生类的生成过程经历了三个步骤:
吸收积累成员
改造积累成员
添加派生类成员
派生类成员的访问控制
在公有派生类中,基类的 public成员和protected成员被继承,分别作为派生类的 public和protected成员。基类的 private成员虽然也被继承了,但在派生类不可见。
在私有派生类中,基类的 public和protected成员被派生类作为自己的 public,protected成员。private成员虽然也被继承了,但在派生类中是不可见的。
#include<iostream>
using namespace std;
class A{
public:
int a;
int b;
private:
int c;
protected:
int d;
};
class B:public A
{
int c;
};
int main(){
cout<<sizeof(A);
cout<<sizeof(B);
}
继承的复制兼容规则
指在程序中需要使用基类对象的任何地方都可以用公有派生类的对象来代替
复制兼容规则中所指的替代包括以下的情况:
派生类的对象可以赋值给基类对象
派生类的对象可以初始化积累的引用
派生类的对象的地址可以赋值给基类类型的指针
通过公有继承,派生类得到了除了构造、析构函数意外的所有成员,且这些成员的访问控制属性也和基类完全相同。这样,他便具备了积累的所有功能。
多态
多态性是指一个名字,各种语义;或界面相同,各种实现。
重载函数是多态性的一种简单形式。
虚函数允许函数调用与函数体的联系在运行时才进行,称为动态联编。
虚函数与动态联编
冠以关键字virtual的成员函数作为虚函数
实现运行时多态的关键首先是要说明虚函数,另外,必须用基类指针调用派生类的不同实现版本。
虚函数的重载特性
在派生类中重载基类的虚函数要求函数名、返回类型、参数个数、参数类型和顺序完全相同。
class base{
public:
virtual void v1();
virtual void v2();
virtual void v3();
void f();
};
class derived:public base
{
void v1();//虚函数
void v2();//重载,参数不同,徐特性丢失
char v3();//error
void f();//非虚函数重载
};
构造函数不能是虚函数,建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的构造函数。
析构函数可以是虚的。虚析构函数用于指引delete运算符正确析构动态对象。
class A
{public:
~A(){cout<<"A::A()is called.\n";}
};
class B:public A
{public:
~B(){cout<<"B::~B()is called.\n";}
};
纯虚函数和抽象类
在许多中情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数。
说明形式:
virtual 类型 函数名(参数表)=0;
一个具有纯虚函数的基类称为抽象类。
class P{/*......*/};
class S
{
P center;
......
public:
P where(){return center;}
void move(P p){center=p;draw();}
virtual void rotate(int)=0;
virtual void draw()=0;//纯虚函数
};
......
S x;//错,抽象类不能创建对象
S *p;//可以声明抽象类指针
S f();//抽象类不能作为函数返回值类型
S &h(S&);//可以声明抽象类的引用