c++继承方式
????派生类继承了基类中除了构造和析构函数外所有部分,并且基类成员在子类中访问属性取决于继承方式。c++类中的成员函数和变量有三种继承方式,分别为:公有继承(public),私有继承(private)和保护继承(protect)。
????public:用该关键字修饰的成员表示公有成员,该成员不仅可以在类内可以被访问,在类外也是可以被访问的,是类对外提供的可访问接口;
????private:用该关键字修饰的成员表示私有成员,该成员仅在类内可以被访问,在类体外是隐藏状态;
????protected:用该关键字修饰的成员表示保护成员,保护成员在类体外同样是隐藏状态,但是对于该类的派生类来说,相当于公有成员,在派生类中可以被访问。
一、公有继承(public)
????公有继承时,基类的公有成员和保护成员在派生类中属性不变,但私有成员不可直接访问。基类成员对派生类对象的可见性为:基类的公有成员可见,保护成员和私有成员不可见,即通过派生类的对象只能访问基类的public成员。
????所以,在公有继承时,派生类的对象可以直接访问基类中的公有成员,派生类的成员函数可以直接访问基类中的公有成员和保护成员。
#include<iostream> using namespace std; class point{ private: int x, y; public: void initpoint(float x1 = 0, float y1 = 0) { x = x1; y = y1; } void move(float xx=0, float yy=0) { x += xx; y += yy; } float getx() const{ return x; } float gety() const { return y; } }; class Rectangle :public point { //公有继承 private: int w, h; public: void initRectangle(float x, float y, float w, float h) { initpoint(x, y); this->w = w; this->h = h; } float geth() const { return h; } float getw() const { return w; } }; int main() { Rectangle rect; rect.initRectangle(2, 3, 20, 30); rect.move(3, 2); cout << rect.getx() << endl; cout << rect.gety() << endl; cout << rect.getw() << endl; cout << rect.geth() << endl; return 0; }
????我们可以看出,在初始化时,由于不能直接初始化基类私有成员,我们直接调用了initpoint这个函数接口。这个函数是基类中的,由于是public方式直接可以使用此基类成员函数。
一、私有继承(public)
????当继承方式为私有继承时,基类的公有成员和保护成员都以私有成员出现在派生类中,同样私有成员在派生类中不可直接访问。此时派生类成员函数可以调用基类公有成员和保护成员,但是在类外部不可使用任何基类成员。可以看出,再进一步派生的话,基类所有成员就无法被直接访问。一般私有继承的使用比较少。
#include<iostream> using namespace std; class point { private: int x, y; public: void initpoint(float x1 = 0, float y1 = 0) { x = x1; y = y1; } void move(float xx = 0, float yy = 0) { x += xx; y += yy; } float getx() const { return x; } float gety() const { return y; } }; class Rectangle :private point { //私有继承 private: int w, h; public: void initRectangle(float x, float y, float w, float h) { initpoint(x, y); this->w = w; this->h = h; } float getx() const { return point::getx(); } float gety() const { return point::gety(); } float geth() const { return h; } float getw() const { return w; } void move(float offx, float offy) { point::move(offx, offy); } }; int main() { Rectangle rect; rect.initRectangle(2, 3, 20, 30); rect.move(1, 1); cout << rect.getx() << endl; cout << rect.gety() << endl; cout << rect.getw() << endl; cout << rect.geth() << endl; return 0; }
????需要注意的是,私有继承后基类成员函数只能在派生类函数中使用,在外部引用会报错。如派生类直接调用move函数时就会报错。为了保证派生类继续拥有基类的接口,就需要重新声明相同的成员例如上例重新声明了getx(),gety(),和move()函数,根据基类隐藏原则基类函数被隐藏,但实现的是相同的效果。
三.保护继承
????在保护继承中,基类公有成员和保护成员都以保护成员出现在派生类中,但基类私有成员仍然不能被直接访问。保护在派生类中被视为公有成员,在类外被视为私有成员。他结合了公有成员和私有成员的优点,更合理地保护成员。私有继承和保护继承的区别中。所有成员的访问属性都完全相同,但是如果派生类继续派生,保护继承下的基类成员一直都存在派生类基类中,但是私有成员将无法访问基类成员。
????保护继承既实现成员隐蔽,又方便继承。
????来看一个错误例子。
#include<iostream> using namespace std; class A { protected: int x; }; int main() { A a; a.x = 1; return 0; }
????我们看出他会报错。
????在没有派生类的情况下,保护类型和私有类型相似,他们都不能在类外访问,否则会报错。但是如果A类以公有派生产生了B类,则在B类中,A中的保护成员像公有成员一样可以直接调用。
#include<iostream> using namespace std; class A { protected: int x; }; class B:public A{ public: void fuc(){ x = 5; cout << x; } }; int main() { B b; b.fuc(); return 0; }
????需要注意的是,如果B是A的派生,B中的成员函数只能通过B的对象访问A中定义的protected成员,而不能通过A的对象访问A中的protected成员。
????三中继承方式总结为下图: