文章目录
前言
继承是c++语言一个重要的机制,该机制自动地为一个类提供来自另一个类的操作和数据结构,这使得程序员只需在新类中定义已有的类中没有的成分来建立一个新类。
一、继承
概念:
继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有的特性基础上进行扩展,增加功能,这样产生新的类,称作是派生类。继承呈现了面向对象程序设计的层析结构,体现了由简单到复杂的认知过程。继承是类设计层次的复用。
三种继承方式:
继承基类成员访问方式的变化:
1.1 公有继承(public)
- 基类的私有成员,子类不可以访问
- 基类的保护成员,子类可以继承为自己的保护成员,在派生类可以访问,在外部不可以访问。
- 基类的公有成员,子类可以继承为自己的公有成员。在派生类可以访问,在外部也可以访问。
#include<iostream>
#include<string>
using namespace std;
class Student
{
public :
Student(string s, int g,int a)
{
cout << "Constuct Student" << endl;
name = s;
grade = g;
age = a;
}
void print()
{
cout << "Student:" << endl;
cout << "name=" << name << endl;
cout << "grade=" << grade<<endl;
cout << "age=" << age << endl;
}
//保护权限
protected:
string name;
int grade;
//私有权限
private:
int age;
};
class GraduateStudent :public Student //公有继承
{
public:
GraduateStudent(string s, int g, int a) :Student(s, g, a) //调用基类的构造函数,构造基类
{
cout << "Constuct GraduateStudent" << endl;
}
/*
公有继承方式,会把基类的公有成员(变量和函数)继承到子类公有成员,保护成员
变成基类的保护成员,但是私有成员子类也一样不可以访问
*/
void print1()
{
cout << "GraduateStudent:" << endl;
cout << "name= " << name << endl;
cout << "grade= " << grade << endl;
}
};
void main()
{
GraduateStudent g("Ouyang", 95, 21);
g.print(); //子类可以直接访问基类公共成员成员
g.print1();
system("pause");
}
1.2 保护继承(protected)
基类公有成员,子类中继承为自己的保护成员,在派生类可以访问,在外部不可以访问
基类保护成员,子类中继承为自己的保护成员,在派生类可以访问,在外部不可以访问
基类私有成员,子类一样不可以访问基类的私有成员。
#include<iostream>
#include<string>
using namespace std;
class Student
{
public :
Student(string s, int g,int a)
{
cout << "Constuct Student" << endl;
name = s;
grade = g;
age = a;
}
void print()
{
cout << "Student:" << endl;
cout << "name=" << name << endl;
cout << "grade=" << grade<<endl;
cout << "age=" << age << endl;
}
string name; //公有成员
int grade;
private:
int age;
};
class GraduateStudent :protected Student //保护继承
{
public:
GraduateStudent(string s, int g, int a) :Student(s, g, a) //调用基类的构造函数,构造基类
{
cout << "Constuct GraduateStudent" << endl;
}
/*
保护继承方式,会把基类的公有成员或者保护成员(变量和函数)变成子类的保护成员,但是私有成员子类也一样不可以访问
*/
void print1()
{
cout << "GraduateStudent:" << endl;
cout << "name= " << name << endl;
cout << "grade= " << grade << endl;
}
};
void main()
{
GraduateStudent g("Ouyang", 95, 21);
//g.print(); 编译出错 无法直接访问子类的公有成员了
g.print1();
system("pause");
}
1.3 私有继承(private)
私有继承方式的,就是在继承时,把protected变成private,它需要注意的事项为:
(1) 基类公有成员,子类中继承为自己的私有成员,在派生类可以访问,在外部不可以访问。
(2). 基类保护成员,子类中继承为自己的私有成员,在派生类可以访问,在外部不可以访问。
(3) 基类私有成员,子类一样不可以访问基类的私有成员。
二、友元类继承
一个友元类的派生类,可以通过其基类接口去访问设置其基类为友元类的类的私有成员,也就是说一个类的友元类的派生类,某种意义上还是其友元类。
#include <iostream>
using namespace std;
class B;
//声明B为A 的友元类
class A
{
int a;
public:
A(int x=0) {
a=x; }
friend class B;
};
class B
{
int b;
public:
void fun(A& ob){
cout << ob.a << endl;}
};
class C:public B
{
public:
//void fun2(A& ob){
cout <<ob.a <<endl;} //派生类新加的函数却不能访问A,此句会报错
};
void main()
{
A a(55);
C c;
c.fun(a); //C是B的派生类 通过基类B的函数fun仍然可以访问
}
三、多态性综合运用
1.多态的实现机制
C++的多态就是基于继承的,多态的实现就是调用虚函数时发生的同名覆盖。当用基类的指针(或引用)指向派生类的对象时,通过该指针(或引用)调用虚方法是动态联编的过程。先找到对象前4个字节的虚函数指针(vbptr),通过vbptr找到虚函数表,虚函数表里有函数的入口地址。
2.C++的静多态和动态多态
静多态是指函数的重载和模板
动多态是指继承中,虚函数的同名覆盖方法
3.实验
3.1代码实现
CShape.h
#pragma once
#ifndef CSHAPE_H
#define CSHAPE_H
#include<string>
#include<math.h>
using namespace std;
class CPoint;
class CRect;
class CShape
{
public:
CShape();
CShape(const CShape& shape);
virtual ~CShape(); //虚函数
virtual double GetArea() const;
virtual bool ptIn(const CPoint& pt) const;
virtual bool InRect(const CRect& rc) const;
virtual void Draw() const;
virtual void DrawColor();
virtual CShape* Clone() const;
virtual CShape& Move(int nOffsetX, int nOffsetY);
被virtual关键字修饰过的成员函数就是虚函数。多态是实现是依赖于虚函数来实现的,之所以虚函数可以分清楚当前调用的函数是基类的还是派生类的,主要在于基类和派生类分别有着自己的虚函数表,再调用虚函数时,它们是通过去虚函数表去对应的函数的。
protected:
string m_sName;
};
class CPoint :public CShape {
public:
int m_nPosX;
int m_nPosY;
CPoint()