基类
class class_A
{
private:
enum{LIM=20};
char name[LIM];
bool tht;
public:
class_A(const char * st = "none",bool ht = false);
void Rname()const;
void Wtht(bool v){tht = v;}
bool Rtht()const{return tht;}
};
class_A::class_A(const char* st,bool ht)
{
std::strncpy(name,st,LIM-2);
name[LIM-1] = '/0';
tht = ht;
}
void class_A::Rname()const {std::cout<<name; }
公有派生(公有继承)
建立一种is-a关系(is-a-kind-of),即派生类对象也是一个基类对象,可以对基类对象执行的任何操作,也可以对派生类对象执行。
基类的公有成员将成为派生类的公有成员;基类的私有部分也将成为派生类的一部分,但只能通过基类的公有和保护方法访问。
class class_B: public class_A
{
private:
int x;
public:
class_B(int r=0,const char * st="none",bool ht=false);
class_B(int r,const class_A & classA);
int Rx(){return x;}
void Wx(int r){x=r;}
};
由于派生类不能直接访问基类的私有成员,所以派生类构造函数必须使用基类的构造函数。
创建派生类对象时,程序首先创建基类对象。概念上说,意味着基类对象应当在程序进入派生类构造函数之前被创建。因此使用成员初始化列表来完成这种工作。关于成员初始化列表的更多介绍请查看<<成员初始化列表(member initializer list)>>
class_B::class_B(int r,const char* st,bool ht):class_A(st,ht){x=r;}
如果不调用基类构造函数,程序将使用默认的基类构造函数:
class_B::class_B(int r,const char* st,bool ht) //:class_A()
{x=r;}
第二个构造函数:
class_B::class_B(int r,const class_A & classA)::class_A(classA){x=r;}
由于classA的类型为const class_A &,因此将调用基类的复制构造函数,如果基类没有定义复制构造函数,编译器将自动生成一个默认的复制构造函数.关于默认复制构造函数的更多介绍请查看<<关于类隐式成员函数>>.
派生类构造函数的要点:
1.基类对象首先被创建;
2.派生类构造函数应通过成员初始化列表将基类信息传递给基类构造函数;
3.派生类构造函数应初始化派生新增的数据成员。
析构函数
释放对象的顺序与创建对象的顺序相反,即首先执行派生类的析构函数,然后自动调用基类的析构函数。
派生类和基类之间的特殊关系
1.派生类对象可以使用基类的非私有方法:
class_B B(100,"Cool",true);
B.Rname(); //derived object uses base method
2.基类(指针、引用)可以在不进行显示类型转换的情况下(指向、引用)派生类对象:
class_B B(100,"Cool",true);
class_A & rt = B;
class_A * pt = &B;
rt.Rname(); //invoke Rname()with reference
pt->Rname(); //invoke Rname()with pointer
不过,基类指针或引用只能用于调用基类方法,因此,不能使用rt或pt来调用派生类的任何方法。另外,不可以将基类对象和地址赋给派生类引用和指针。因为,如果允许基类引用隐式地引用派生类对象,则可以使用基类引用为派生类对象调用基类的方法。派生类继承了基类的方法,这样做不会出现问题。但要是可以将基类对象赋给派生类引用,则能够为基类对象调用派生类方法,这样做将出现问题。
引用这一特性,能够将基类对象初始化为派生类对象,例如:
class_B B(100,"Cool",true);
class_A A(B);
要初始化A,匹配的构造函数的原型为:
class_A(const class_B &); //doesn't exist
类定义中没有这样的构造函数,但存在隐式复制构造函数:
//implicit copy constructor
class_A(const class_A &);
形参是基类引用,因此它可以引用派生类。它将A初始化为嵌套在class_B对象B中的class_A对象。
还可以将派生对象赋给基类对象:
class_B B(100,"Cool",true);
class_A A;
A = B; //assign derived to base object
这种情况下,程序将使用隐式重载赋值操作符:
class_A & operator=(const class_A &)const;
因此B的基类部分被复制给A。