一.继承的含义
创新互联建站是专业的大通网站建设公司,大通接单;提供成都网站制作、网站建设,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行大通网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!继承是面向对象复用的重要手段。通过继承定义一个类,它们的类型之间的关系建模,共享公有的东西,实现各自本质不同的东西。
二.继承关系与访问限定符
有如下总结:
1.基类的私有成员在派生类中是不能被访问的,如果一些基类成员不想被基类对象直接访问,但需要在派生类中能访问,就定义为保护成员。可以看出保护成员限定符是因继承才出现的。
例如:
class Date { public: Date() { cout << "Date()" << endl; } ~Date() { cout << "~Date()" << endl; } void Display() { cout << _year << "-" << _month << "-" << _day << endl; } public: int _year; protected: int _month; private: int _day; }; class Time : public Date { public: Time() { cout << "Date()" << endl; } ~Time() { cout << "~Date()" << endl; } void Display() { cout << _year << "-"; cout << _month << "-"; //cout<< _day << "-"; //派生类中不能访问基类的private成员。 cout << _hour << "-" << _minute << "-" << _second << endl; } public: int _hour; protected: int _minute; private: int _second; };
2.public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可用,因为每个子类对象也都是一个父类对象。
void Test1() { Time t; Date t1; //t = t1; //父类对象不可以给子类对象赋值 t1 = t; //子类对象不可以给父类对象赋值 Time* p1 = NULL; Date* p2 = NULL; p2 = &t; //父类的指针/引用可以指向子类对象 //p1 = &t1; //子类的指针/引用不能指向父类对象(可以通过强制类型转换完成) t._hour = 0; }
3.protetced/private继承是一个实现继承,基类的部分成员并未完全成为子类接口的一部分,是 has-a 的关系原则。
4. 不管是哪种继承方式,在派生类内部都可以访问基类的公有成员和保护成员,但是基类的私有成员存在但是在子类中不可见(不能访问)。
class Date { public: Date() { cout << "Date()" << endl; } ~Date() { cout << "~Date()" << endl; } void Display() { cout << _year << "-" << _month << "-" << _day << endl; } public: int _year; protected: int _month; private: int _day; }; class Time : protected Date { public: Time() { cout << "Date()" << endl; } ~Time() { cout << "~Date()" << endl; } void Display() { cout << _year << "-"; cout << _month << "-"; //cout<< _day << "-"; cout << _hour << "-" << _minute << "-" << _second << endl; } public: int _hour; protected: int _minute; private: int _second; }; void test2() { Time t; t._year = 0; t._month = 0; //不能在外界访问父类的公有成员和保护成员。 t._hour = 0; }
5.使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
6.继承体系中的作用域
(1).继承体系中基类和派生类都有独立的作用域。
(2).子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以使用 基类::基类成员 访问)--隐藏
class Date { public: Date() { cout << "Date()" << endl; } ~Date() { cout << "~Date()" << endl; } void Display() { cout << _year << "-" << _month << "-" << _day << endl; } public: int _year; protected: int _month; private: int _day; }; class Time : protected Date { public: Time() { cout << "Date()" << endl; } ~Time() { cout << "~Date()" << endl; } void Display() { Date::Display(); //可以通过这样的方式访问 cout << _hour << "-" << _minute << "-" << _second << endl; } public: int _hour; protected: int _minute; private: int _second; }; void test3() { Time t; t.Display(); //在外部调用,调用的是父类的函数 }
三.派生类的成员函数
在继承关系里面,在派生类中如果没有显示定义这六个成员函数,编译系统则会默认合成这六个默认的成员函数。且会调用父类的构造函数。
class Date { public: Date() { cout << "Date()" << endl; } ~Date() { cout << "~Date()" << endl; } void Display() { cout << _year << "-" << _month << "-" << _day << endl; } public: int _year; protected: int _month; private: int _day; }; class Time : protected Date { public: void Display() { Date::Display(); cout << _hour << "-" << _minute << "-" << _second << endl; } public: int _hour; protected: int _minute; private: int _second; }; void test3() { · Time t; 00182A9D lea ecx,[t] 00182AA0 call Time::Time (01813FCh) //通过汇编代码看出调用了构造函数 00182AA5 mov dword ptr [ebp-4],0 t.Display(); }
四.菱形继承与虚继承
从上面经典的菱形继承可以看出,C类里面保存了两份A类的值,在空间上造成了冗余浪费,且访问时,要显示指定访问哪个父类的成员。
class A { public: A(int data = 0) :_a(data) {} //private: int _a; }; class B1 : public A { public: B1(int data=0) :_b1(data) {} private: int _b1; }; class B2 : public A { public: B2(int data = 0) :_b2(data) {} private: int _b2; }; class C :public B1,public B2 { public: C(int data = 0) :_c(data) {} void fun() { //_a = 0; //指示不明确。 B1::_a = 1; B2::_a = 2; } private: int _c; };
虚继承在继承方式前加关键字virtual,它解决了在菱形继承体系里面子类对象包含多份父类对象的数据冗余&浪费空间的问题。
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。