类的继承与派生
所谓继承结束从先辈处得到属性和行为特征。类的继承是新的类从已有类处得到已有的特性,从另外一个角度说就是已有类通过派生得到新类。
原有类称为基类,新类称为派生类或子类。派生类同样也可以作为基类派生新类,这样就形成了类的层次结构。类的派生实际上说一种演化,即通过扩展,更改和特殊化,从一个已知类出发建立一个新类,通过类的派生可以建立具有共同关键特征的对象家族,从而实现代码的重用,这种继承与派生的机制对于已有程序的发展和改进是极为有利的。
派生类的定义
在c++中派生类一般定义的语法为:
class 派生类名:继承方式(public/private/protected) 基类名1,.......{ 派生类成员声明; }
·一个派生类可以同时有几个基类,称为多继承;只有一个基类的情况下称为单继承。
·继承方式规定类如何访问基类的成员。继承方式的关键词为:public/private/protected,分别表示公有继承,私有继承和保护继承。如果不显式的给出继承方式系统默认为私有继承。
·在类的继承中,派生类包含了它的全部基类中除构造函数和析构函数之外的所有成员。
·访问控制
·公有继承
基类的公有成员和保护成员的访问属性在派生类中不变,而基类的私有成员不可直接访问。
class Point { private: float x, y; public: void initP(float xx, float yy) { x = xx; y = yy; } void Move(float xOff, float yOff); float GetX()const { return x; } float GetY()const { return y; } }; void Point::Move(float xOff, float yOff) { x += xOff; y += yOff; } class Rectangle:public Point { private: float W, H; public: void initR(float x, float y, float w, float h) { initP(x, y); W = w; H = h; } float GetH()const { return H; } float GetW()const { return W; } }; int main() { Rectangle R; R.initR(1, 2, 3, 4); R.Move(5, 6); cout << "x=" << R.GetX() << endl; cout << "y=" << R.GetY() << endl; cout << "W=" << R.GetW() << endl; cout << "H=" << R.GetH() << endl; return 0; }
·私有继承
基类中的公有成员和保护成员都以私有成员身份出现在派生类中,而基类的私有成员在派生类中不可直接访问。
#include<iostream> using namespace std; class Point { private: float x, y; public: void initP(float xx, float yy) { x = xx; y = yy; } void Move(float xOff, float yOff); float GetX()const { return x; } float GetY()const { return y; } }; void Point::Move(float xOff, float yOff) { x += xOff; y += yOff; } class Rectangle:private Point { //私有继承 private: float W, H; public: void initR(float x, float y, float w, float h) { initP(x, y); W = w; H = h; } float GetH()const { return H; } float GetW()const { return W; } }; int main() { Rectangle R; R.initR(1, 2, 3, 4); R.Move(5, 6); cout << "x=" << R.GetX() << endl; cout << "y=" << R.GetY() << endl; cout << "W=" << R.GetW() << endl; cout << "H=" << R.GetH() << endl; return 0; }
此时主函数中调用move和get函数报错,因为move和get函数此时为私有函数。
·保护继承
基类中的公有和保护成员都以保护成员的身份出现在派生类中,而基类的私有成员不可访问。
#include<iostream> using namespace std; class Point { private: float x, y; public: void initP(float xx, float yy) { x = xx; y = yy; } void Move(float xOff, float yOff); float GetX()const { return x; } float GetY()const { return y; } }; void Point::Move(float xOff, float yOff) { x += xOff; y += yOff; } class Rectangle:protected Point { //保护继承 private: float W, H; public: void initR(float x, float y, float w, float h) { initP(x, y); W = w; H = h; } float GetH()const { return H; } float GetW()const { return W; } }; int main() { Rectangle R; R.initR(1, 2, 3, 4); R.Move(5, 6); cout << "x=" << R.GetX() << endl; cout << "y=" << R.GetY() << endl; cout << "W=" << R.GetW() << endl; cout << "H=" << R.GetH() << endl; return 0; }
此时主函数中调用move和get函数报错,因为move和get函数此时为保护函数,不可被外部调用。
从继承的访问规则可以看到类中保护成员的特征。如果类中含保护成员则该类的私有成员和保护成员一样不可访问。 而它的派生类能访问其保护成员,但是绝不可能被外部使用者访问。这样,如果合理地利用保护成员,就可以在类的复杂层次关系中共享与成员隐藏之间找到一个平衡点,既能实现成员隐藏又能方便继承,实现代码的高效重用与扩充。
·对基类函数的隐藏
如果派生类的声明中声明了一个和某基类成员同名的新成员(如果水成员函数则参数表也要相同),派生的新成员就隐藏了外层的同名成员,这称作同名隐藏。
#include<iostream> using namespace std; class Point { private: float x, y; public: void initP(float xx, float yy) { x = xx; y = yy; } void Move(float xOff, float yOff); float GetX()const { return x; } float GetY()const { return y; } }; void Point::Move(float xOff, float yOff) { x += xOff; y += yOff; } class Rectangle:public Point { private: float W, H; public: void initR(float x, float y, float w, float h) { initP(x, y); W = w; H = h; } void Move(float a, float b) { } //同名隐藏 float GetH() const{ return H; } float GetW() const{ return W; } }; int main() { Rectangle R; R.initR(1, 2, 3, 4); R.Move(5, 6); cout << "x=" << R.GetX() << endl; cout << "y=" << R.GetY() << endl; cout << "W=" << R.GetW() << endl; cout << "H=" << R.GetH() << endl; return 0; }
此时主函数中的Move函数调用的为Rectangle中的Move函数