语法形式如下:
class 派生类名: 基类名表
{
数据成员和成员函数声明
基类名表 构成
接下来引用一段代码来详细的表示一下引用过程:
#include<iostream>
using namespace std ;
class A
{ public :
void get_XY() { cout << "Enter two numbers of x, y : " ; cin >> x >> y ; }
void put_XY() { cout << "x = "<< x << ", y = " << y << '\n' ; }
protected: int x, y ;
};
class B : public A
{ public :
int get_S() { return s ; };
void make_S() { s = x * y ; }; // 使用基类数据成员x,y
protected: int s;
};
class C : public B
{ public :
void get_H() { cout << "Enter a number of h : " ; cin >> h ; }
int get_V() { return v ; }
void make_V() { make_S(); v = get_S() * h ; } // 使用基类成员函数
protected: int h, v;
};
int main()
{ A objA ;
B objB ;
C objC ;
cout << "It is object_A :\n" ;
objA.get_XY() ;
objA.put_XY() ;
cout << "It is object_B :\n" ;
objB.get_XY() ;
objB.make_S() ;
cout << "S = " << objB.get_S() << endl ;
cout << "It is object_C :\n" ;
objC.get_XY() ;
objC.get_H();
objC.make_V() ;
cout << "V = " << objC.get_V() << endl ;
}
派生类构造函数 ( 变元表 ): 基类 ( 变元表 ), 对象成员1(变元表 )
… 对象成员n ( 变元表 );
#include<iostream>
using namespace std ;
class Base
{ public : Base ( ) { cout << "Base created.\n" ; }
} ;
class D_class : public Base
{ public : D_class ( ) { cout << "D_class created.\n" ; }
} ;
int main ( )
{ D_class d1 ; }
四、派生类构造函数和析构函数的定义规则
(一) 派生类构造函数和析构函数的使用原则
在C++中,派生类构造函数的一般格式为:
派生类::派生类名(参数总表):基类名(参数表)
{
// 派生类新增成员的初始化语句
}
注意:这是基类有构造函数且含有参数时使用
class B
{
public:
B() { cout<<"B()"<<endl; }
~B() { cout<<"~B()"<<endl; }
};
class D : public B
{
public:
D(){ cout<<"D()"<<endl; }
~D() { cout<<"~D()"<<endl; }
};
int main()
{
D d;
return 0;
}
即先调用D的析构函数,再调用B的析构函数
例题:考察一个点、圆、圆柱体的层次结构
class Point
{ friend ostream &operator<< (ostream &, const Point &);
public:
Point( int = 0, int = 0 ) ; // 带默认参数的构造函数
void setPoint( int, int ) ; // 对点坐标数据赋值
int getX() const { return x ; } int getY() const { return y ; }
protected: int x, y; // Point类的数据成员
};
class Circle : public Point
{ friend ostream &operator<< (ostream &, const Circle &); // 友元函数
public:
Circle(double r=0.0, int x=0, int y=0); // 构造函数
void setRadius(double); /*置半径*/ double getRadius() const; /*返回半径*/
double area() const; // 返回面积
protected: double radius; // 数据成员,半径
};
class Cylinder:public Circle
{ friend ostream & operator<<(ostream &, const Cylinder &); // 友元函数
public:
Cylinder(double h=0.0, double r=0.0, int x=0, int y=0); // 构造函数
void setHeight(double); /* 置高度值*/ double getHeight() const; /* 返回高度值*/
double area() const; /* 返回面积*/ double volume() const; /* 返回体积*/
protected: double height; // 数据成员,高度
};
五、多继承
class 派生类名: 访问控制 基类名1, 访问控制 基类名2, … , 访问控制 基类名n
{
数据成员和成员函数声明
};
(一)多继承的派生类构造和访问
派生类名(参数总表):基类名1(参数表1),基类名2(参数表2),…,基类名n(参数表n)
{
// 派生类新增成员的初始化语句
}
多继承方式下构造函数的执行顺序:
先执行所有基类的构造函数
再执行对象成员的构造函数
最后执行派生类的构造函数
处于同一层次的各基类构造函数的执行顺序取决于定义派生类时所指定的基类顺序
与派生类构造函数中所定义的成员初始化列表顺序没有关系。
内嵌对象成员的构造函数执行顺序与对象在派生类中声明的顺序一致
六、赋值兼容规则
(一)赋值兼容规则指在程序中需要使用基类对象的任何地方,都可以用公有派生类的对象来替代。
赋值兼容规则中所指的替代包括以下的情况:
a派生类的对象可以赋给基类对象
b派生类的对象可以初始化基类的引用
c派生类的对象的地址可以赋给基类类型的指针
(1) 可以用派生类对象给基类对象赋值。例如:
Base b;
Derived d;
b=d;
这样赋值的效果是, 对象 b 中所有数据成员都将具有对象d 中对应数据成员的值。(2) 可以用派生类对象来初始化基类的引用。例如:
Derived d;
Base &br=d;
(3) 可以把派生类对象的地址赋值给指向基类的指针。例如:
Derived d;
Base *bptr=&d;
这种形式的转换,是在实际应用程序中最常见到的。
(4) 可以把指向派生类对象的指针赋值给指向基类对象的指针。例如:
Derived *dptr,obj; dptr=&obj;
Base *bptr=dptr;
(三)赋值兼容应注意的问题(1)声明为指向基类的指针可以指向它的公有派生类的对象,但不允许指向它的私有派生类的对象。例如:
class B {…};
class D:privateB {…};
B b1,*pbl;D d1;
pb1=&b1; //合法,基类B的对象b1和B类的指针
pb1=&d1; //非法,不允许将基类指针指向它的私有派生类对象
(2)允许将一个声明为指向基类的指针指向其公有派生类对象,但是不能将一个声明为指向派生类对象的指针指向其基类的一个对象。
(3) 声明为指向基类对象的指针,当其指向公有派生类对象时,只能用它来直接访问派生类中从基类继承来的成员,而不能直接访问公有派生类的定义的成员。
七、心得体会
继承确实是一个比较实用的模块。在已有类的基础上创建新类的过程一个B类继承A类,或称从类A派生类B,A称为基类,B称为派生类,确实能在写代码的过程中省下不少功夫,比如用户类中有管理类的部分操作,就完全可以使用继承来减少工作量。学习到现在的过程中,渐渐掌握了更多新的,方便的知识,能够使自己的代码更优化,继承就是其中之一。不仅减少了代码长度,减少了工作量,而且代码更条理了,是挺好用的技能。