C++继承模式详解

发布时间:2026/5/31 6:55:50

C++继承模式详解 继承继承的概念继承机制是面向对象程序设计使代码可以复用的最重要的手段它允许程序员在保持原有类特性的基础上进行扩展增加功能。继承呈现了面向对象程序设计的层次结构体现了由简单到复杂的认知过程。继承的定义上面的基类也可以叫父类派生类也可以叫子类。继承关系和访限定符继承方式接下来用代码测试上面的继承方式123456789101112131415161718classPerson{public:voidPrint (){cout_name endl;}protected:string _name 张三;// 姓名private:int_age 18 ;// 年龄};classStudent :publicPerson{protected:int_stunum 22;// 学号};public继承上面是给的缺省值来测试没写构造函数s就继承了Person的name,age基类中private的age在物理上继承了但在语法上但是不能访问的。也可以调用基类的成员函数但是不能直接访问基类中private的成员prootected可以在派生类中访问不能再在类外访问protected继承protected继承在类外连基类的public成员函数都不能用了只能在派生类的类里面使用。同样基类中私有的不能访问private继承就都是私有的了。总结1.基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。2.基类private成员在派生类中是不能被访问如果基类成员不想在类外直接被访问但需要在派生类中能访问就定义为protected。可以看出保护成员限定符是因继承才出现的.3.基类的私有成员在子类中都是不可见的其他成员在子类中等于权限最小的那个4.class的默认继承方式是private,struct默认的继承方式是public最好显示的写出继承方式5.在实际应用一般使用public继承很少使用protected和private。父类和子类对象赋值转化123456789101112classPerson{protected:string _name;// 姓名string _sex;// 性别int_age;// 年龄};classStudent :publicPerson{public:int_No;// 学号};子类可以给父类父类不能给子类不仅可以是子类的对象也可以是指针和引用12345Student s;Person p;p s;Person *ptr s;//子类赋给父类指针Person ref s;//子类赋给父类引用派生类对象 可以赋值给 基类的对象 / 基类的指针 / 基类的引用。这里有个形象的说法叫切片或者切割。寓意把派生类中父类那部分切来赋值过去。基类对象不能赋值给派生类对象基类的指针可以通过强制类型转换赋值给派生类的指针。但是必须是基类的指针是指向派生类对象时才是安全的。等到子类中的默认函数就会用到切片继承中的作用域123456789101112131415161718classPerson{protected:string _name 法外狂徒;// 姓名int_num 11;// 身份证号};classStudent :publicPerson{public:voidPrint(){cout 姓名: _name endl;cout 身份证号: _num endl;cout 学号: _num endl;}protected:int_num 2;// 学号};还有成员函数的隐藏12345678910111213141516171819202122classA {public:voidfun(doublex){cout fun()-x x endl;}};classB :publicA {public:voidfun(inti){cout fun()- i endl;}};intmain(){B b;b.fun(10);b.A::fun(11.1);//加作用域return0;}父类和子类函数名相同不是重载而是隐藏函数重载是在同一作用域不同的作用域是隐藏在子类成员函数中可以使用 基类::基类成员 显示访问在写代码中最好不要定义同名的成员子类的默认成员函数在类和对象的时候讲了6个默认的成员函数现在子类中讲4个构造拷贝构造赋值和析构12345678910111213141516171819202122232425262728293031classPerson//父类{public:Person(constchar* name 李四): _name(name){cout Person() endl;}Person(constPerson p): _name(p._name){cout Person(const Person p) endl;}Person operator(constPerson p){cout Person operator(const Person p) endl;if(this! p)_name p._name;return*this;}~Person(){cout ~Person() endl;}protected:string _name;// 姓名};1234567891011121314151617181920212223242526272829303132333435363738//子类classStudent :publicPerson{public://构造函数Student(constchar* name,intnum): Person(name)//调用父类的构造函数初始化父类的成员, _num(num)//初始化子类的成员{cout Student() endl;}//拷贝构造Student(constStudent s): Person(s)//这里就用到了切片切父类的成员类拷贝, _num(s._num)//拷贝子类的{cout Student(const Student s) endl;}Student operator (constStudent s){cout Student operator (const Student s) endl;if(this! s){Person::operator (s);//调用父类的赋值_num s._num;//赋值子类自己的}return*this;}~Student(){//子类的析构函数完成清理后会自动调用父类的析构函数cout ~Student() endl;}protected:int_num;//学号};总结派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数则必须在派生类构造函数的初始化列表阶段显示调用。派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。派生类的operator必须要调用基类的operator完成基类的复制。派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。派生类对象初始化先调用基类构造再调派生类构造。派生类对象析构清理先调用派生类析构再调基类的析构。继承与友元友元关系不能继承父类友元不能访问子类私有和保护成员1234567891011121314151617181920212223242526classStudent;classPerson{public:friendvoidDisplay(constPerson p,constStudent s);protected:string _name;// 姓名};classStudent :publicPerson{public:friendvoidDisplay(constPerson p,constStudent s);protected:int_stuNum;// 学号};voidDisplay(constPerson p,constStudent s) {cout p._name endl;//可以访问cout s._stuNum endl;//要在子类中加上友元才能访问,不加会报错}intmain(){Person p;Student s;Display(p, s);return0;}继承与静态成员基类定义了static静态成员则整个继承体系里面只有一个这样的成员。无论派生出多少个子类都只有一个static成员实例 。

相关新闻