我们在定义对象的时候,会发现很多的对象之间都是有联系的,如以下两个类:
class Person{public: void eat(); string m_strName; int m_iAge;};class Worker{public: void eat(); void work(); string m_strName; int m_iAge; int m_iSalary;};worker中的一些成员也是person的成员,应对这种情况,为了减轻程序员的工作量,C++设计了继承。 有了继承,我们可以把worker类写成下面那样,不必把person类再写一遍。其中worker是person的派生类,person是worker的 基类。
class Worker:public Person{public: void work(); int m_iSalary;};这里有一个需要知道的,我们在实例化一个派生类的对象时,会先构造基类,再构造派生类,而析构时则顺序相反,具体的顺序如下 person() worker() ~worker() ~person()
C++的继承方式有3种 class A::public B//公有继承 class A::PRotected B//保护继承 class A::private B//私有继承
其中protected在不涉及到继承关系时,其特性和private的性质是一样的。
class Person{public: Person();//构造函数 ~Person();//析构函数 void eat(); protected: int m_iAge;private: string m_strName;};当做如下访问时,会出现错误,因为赋值的不在public下
int main(){ Person person; person.eat(); person.m_iAge = 20;//错误 person.m_strName = "jim";//错误 return 0;}当在继承时,做如下定义
class Person{public: Person();//构造函数 ~Person();//析构函数 void eat(); protected: int m_iAge; string m_strName;};当为protected时,相关的对象成员能够继承到如下位置。其中void work()能够访问继承来的m_iAge
class Worker :public Person//公有继承{public: Worker();//构造 ~Worker();//析构 void eat();//继承person的 void work(){ m_iAge = 20; }protected: string m_strName;//继承person int m_iAge;//继承person int m_iSalary;};如果将以上代码中的protected换成private,代码如下
class Person{public: Person();//构造函数 ~Person();//析构函数 void eat(); private: int m_iAge; string m_strName;};class Worker :public Person//公有继承{public: Worker();//构造 ~Worker();//析构 void eat();//继承person的 void work(){ m_iAge = 20; }//这样访问错误private: //private中的m_strName和m_iAge被继承到了不可见位置 int m_iSalary;};此时的void work()不可调用继承来的m_iAge,因为private中的m_strName和m_iAge被继承到了不可见位置。
总结一下 1.当两个类产生了继承关系,而继承方式是public,那么基类下的public成员会被继承到派生类的public下面;基类下的protected成员会被继承到派生类的protected成员下;基类的privated成员将会无法访问。 2.当两个类产生了继承方式,而继承方式是protected,那么基类下的public成员会被继承到派生类的protected下面;基类下的protected成员会被继承到派生类的protected成员下;基类的privated成员将会无法访问。 3.当两个类产生了继承关系,而继承方式是private,那么基类下的public成员会被继承到派生类的private下面;基类下的protected成员会被继承到派生类的private成员下;基类的privated成员将会无法访问。
C++中有两个很容易的混淆概念:覆盖和隐藏。那么什么是隐藏?假如B是A的派生类,两个类有相同函数名的成员函数,比如void ABC(),这时,子类中的void ABC()会自动隐藏父类中的void ABC(),但并没有消失,可以通过特殊的手段访问,数据成员也有隐藏这种现象。那么什么是覆盖呢?如果我们没有在子类中定义同名的虚函数,那么在子类虚函数表当中就会写上父类当中那个虚函数的函数入口地址,如果我们在子类中也定义了同名的虚函数,那么在子类的虚函数表当中,我们就会把原来父类的虚函数的函数地址覆盖一下,覆盖成子类的虚函数的函数地址【关于虚函数表涉及请看多态的实现原理篇】
新闻热点
疑难解答
图片精选