C++实验2 继承和多态

C++实验2 继承和多态,第1张

C++实验2 继承和多态

目录

实验内容

一、继承访问

1.设计类A具有public, protected, private等不同属性的成员函数变量

2.在类B中添加public, protected, private等不同属性的成员函数或变量;类B通过public, protected, private等不同方式继承A,在类B的成员函数中测试访问A的成员函数或变量:

2.1类B通过public方式继承A,测试访问A的成员函数或变量:

 2.2类B通过protected方式继承A,测试访问A的成员函数或变量:

2.3类B通过private方式继承A,测试访问A的成员函数或变量:

3.B以private方式继承A,尝试把A中的部分public成员提升为public。

继承类总结:

二、友元类继承

1.设计类A含有私有变量a,在类A中友元给类C;

2.设计类B继承A,添加私有变量b;在类C中测试访问类B的成员变量a, b;

3.设计类D继承C,在D的成员函数中测试访问类A的成员变量a,类B的成员变量a, b。

三.多态性综合运用

1.一般多态性函数:输入输出参数完全一样,在父类中添加virtual;

2.特殊多态性函数:输入或输出参数在子类中是父类的指针或基类的引用,在子类中对于的是子类的指针或子类的引用:

 3.析构函数的多态性:

 4.虚继承:

总结:



实验内容

一、继承访问权限测试
设计类A具有public, protected, private等不同属性的成员函数或变量;
类B通过public, protected, private等不同方式继承A,在类B的成员函数中测试访问A的成员函数或变量;
在类B中添加public, protected, private等不同属性的成员函数或变量,在外部测试访问B的各个成员函数或变量;
B以private方式继承A,尝试把A中的部分public成员提升为public。
二、友元类继承测试
设计类A含有私有变量a,在类A中友元给类C;
设计类B继承A,添加私有变量b;在类C中测试访问类B的成员变量a, b;
设计类D继承C,在D的成员函数中测试访问类A的成员变量a,类B的成员变量a, b。
三、多态性综合运用
一般多态性函数:输入输出参数完全一样,在父类中添加virtual;
特殊多态性函数:输入或输出参数在子类中是父类的指针或基类的引用,在子类中对于的是子类的指针或子类的引用;
析构函数的多态性;
多继承,注意什么情况需要虚继承;
设计矢量图,运用多继承设计组合图形,要求具备创建不同类型矢量图、选择图形、移动图形、用不同颜色显示图形(表示选中与否),用vector或数组管理图形。
 

 

一、继承访问 1.设计类A具有public, protected, private等不同属性的成员函数或变量;
class Person   //A类
{
public:                                //公有函数成员
    string m_strName;                  //姓名
    Person();
    virtual ~Person();
    Person(string strName,string strSex,int Age);
    void SetSex(string strSex)
    {
        m_strSex = strSex;
    }

protected:                             //保护数据成员
    string m_strSex;                   //性别

private:                               //私有数据成员
    int m_nAge;                        //年龄
};
2.在类B中添加public, protected, private等不同属性的成员函数或变量;类B通过public, protected, private等不同方式继承A,在类B的成员函数中测试访问A的成员函数或变量: 2.1类B通过public方式继承A,测试访问A的成员函数或变量:
class Student: public Person   //B类继承A类
{
public:
    Student();
    ~Student();
    void SetType();

    void SetName(string strName="")    //隐含的内联函数
    {
        m_strName = strName;         //student通过public继承Person在类的内部可以访问
    }
    void SetSex(string strSex="")
    {
        m_strSex = strSex;        public方式继承父类protect变量可以访问
    }
    void SetAge(int Age)
    {
        //m_nAge = Age;         //public继承方式不能访问private变量
    }
    inline string GetSex();
protected:
    double m_nNumber;           //学生成绩
private:
    string m_nScore;          //学生学号
};
void TestPerson()
{
    Person per;
    per.m_strName = "tjw";
    //per.m_strSex = "";            //父类Person的protected属性在外部无法访问
    //per.m_nAge = 0;               //父类private属性在外部也无法访问
    Student stu;
    stu.m_strName = "tjw";
    //stu.m_strSex = "man";       //public继承下,父类的protected属性同样无法在外部被子类访问
    //stu.m_nAge = 0;             //public继承下,父类的private属性无法在外部被子类访问
}
 2.2类B通过protected方式继承A,测试访问A的成员函数或变量:
class Worker:protected Person
{
public:
    void SetName(string strName="")
    {
        m_strName = strName;         //Worker通过protected继承Person在类的内部可以访问
    }
    void SetSex(string strSex="")
    {
        m_strSex = strSex;          //父类protected属性用protected继承也可以访问
    }
    void SetAge(int Age)
    {
        //m_nAge = Age;             //protected继承方式不能访问private变量
    }
    string & GetName()
    {
        return m_strName;
    }
};
//使用protected来继承的话,原有自由度高于protected的变量都会被降级成protected
void TestPerson()
{
    Worker worker;
    worker.SetName("zzz");//protected变量在外部无法被访问,该行代码无法运行
    worker.m_strName="";//protected变量无法在外部函数中被访问
    worker.m_strSex ="man";//private变量无法在外部函数中被访问

}
2.3类B通过private方式继承A,测试访问A的成员函数或变量:
class Teacher:private Person
{
public:
    void SetName(string strName="")
    {
        m_strName = strName;         //Teacher类通过private继承Person在类的内部可以访问
    }
    void SetSex(string strSex="")
    {
        m_strSex = strSex;          //父类protected属性用private继承也可以访问
    }
    void SetAge(int Age)
    {
        //m_nAge = Age;             //private继承方式不能访问private变量
    }

};
//使用private来继承父类,原有权限高于private的变量都会被降成private
void TestPerson()
{
    Teacher teacher;
    teacher.m_strName = "";//private变量无法在外部函数中被访问
    teacher.m_strSex = "";//private变量无法在外部函数中被访问
    teacher.m_nAge = 0;//private变量无法在外部函数中被访问
}
3.B以private方式继承A,尝试把A中的部分public成员提升为public。
class Teacher:private Person
{
public:
    using Person::m_strName;       
    using Person::m_strSex; //将基类的protected变量变为public访问级别
    using Person::m_nAge;
    string & GetName()              
    {
        return m_strName;
    }
    void SetName(string strName="")
    {
        m_strName = strName;         //Teacher类通过private继承Person在类的内部可以访问
    }
    void SetSex(string strSex="")
    {
        m_strSex = strSex;          //父类protected属性用private继承也可以访问
    }
    void SetAge(int Age)
    {
        //m_nAge = Age;             //private继承方式不能访问private变量
    }

};
void TestPerson()
{
    Teacher teacher;
    //用protected,private继承的不能被外部访问,可以用using提升访问权限到public
    teacher.m_strName = "";
    teacher.m_strSex = "";
    //若不用using提升访问权限,则父类public,protected,private的变量均无法访问

}
继承类总结:

1.继承类只能访问父类protected级以上的变量或成员函数,不能访问private

2.用protected,private继承的不能被外部访问,可以用using提升访问权限到public进而访问;

二、友元类继承 1.设计类A含有私有变量a,在类A中友元给类C;
class Person   //A类
{
public:                                //公有函数成员
    string m_strName;                  //姓名
    Person();
    Person(string strName,string strSex,int Age);
    void SetSex(string strSex)
    {
        m_strSex = strSex;
    }
    friend class Teacher;       //将Teacher类设置成Person类的友元类,使其子类所有函数均可访问父类成员
    friend void A::TestFriend(Person &per);    //友元成员函数,只允许TestFriend()访问私有量
    //友元成员函数:在类A的内部声明一个属于类B的成员函数,则只有该成员才能访问类A的私有成员
    friend void TestFriendFun(Person &per)  //友元函数(全局),同样可以访问私有变量(第一种实现方式:实现过程在类的内部)
    {
        per.m_nAge =20;
    }
    friend void TestFriendFun(Person &per); //第二种实现方式:实现过程在类的外部
    friend istream & operator>>(istream &is,Person &per);
    friend ostream & operator<<(ostream &os,const Person &person);
    bool Create(string strName,string strSex,int Age);

protected:                             //保护数据成员
    string m_strSex;                   //性别

private:                               //私有数据成员
    int m_nAge;                        //年龄 即a
};
2.设计类B继承A,添加私有变量b;在类C中测试访问类B的成员变量a, b;
class Student:public Person //B
 {
public:
    ~ Student();
    void Person_Career(Person& p);
    void Student_Career(Student& p);
    void returnCareer();
    using Person::m_strSex;
    using Person::m_strName;
    //使用这两行代码可以将因为继承方式采用private而导致sex和name两个属性改为public公开
    Student();
    string m_nSubject;
    void SetSex(string strSex="")
    {
        m_strSex = strSex;//内部函数可以访问protected变量,外部不行
    }//隐藏内联函数
private:
    double m_nScore; //考试分数 即b
protected:
    string m_nNumber; //学生学号


   inline string GetSex();  //显示内联函数
};

3.设计类D继承C,在D的成员函数中测试访问类A的成员变量a,类B的成员变量a, b。
class D:protected Teacher  //D
{
public:
	Person person;
	Student student;
	void visit() {
		//person.m_nAge = 1;      //类A的成员变量a无法访问
		//student.m_nAge = 2;     //类B的成员变量a无法访问
		//student.m_nScore = 1;   //类B的成员变量b无法访问
	}
};

 

三.多态性综合运用 1.一般多态性函数:输入输出参数完全一样,在父类中添加virtual;

通过使用virtual关键字对多态进行支持,被virtual声明的函数被重写后具有多态特性,被virtual声明的函数叫做虚函数

class Person   //A类
{
public:                                //公有函数成员
    string m_strName;                  //姓名
    Person();
    virtual ~Person();
    Person(string strName,string strSex,int Age);
    virtual void SetType();
    //virtual void SetWork() =0;     //纯虚函数
    void SetSex(string strSex)
    {
        m_strSex = strSex;
    }
    friend class Teacher;       //将Teacher类设置成Person类的友元类,使其子类所有函数均可访问父类成员
    friend void A::TestFriend(Person &per);    //友元成员函数,只允许TestFriend()访问私有变量
    //友元成员函数:在类A的内部声明一个属于类B的成员函数,则只有该成员才能访问类A的私有成员
    friend void TestFriendFun(Person &per)  //友元函数(全局),同样可以访问私有变量(第一种实现方式:实现过程在类的内部)
    {
        per.m_nAge =20;
    }
    friend void TestFriendFun(Person &per); //第二种实现方式:实现过程在类的外部

    friend istream & operator>>(istream &is,Person &per);
    friend ostream & operator<<(ostream &os,const Person &person);
    bool Create(string strName,string strSex,int Age);

protected:                             //保护数据成员
    string m_strSex;                   //性别

private:                               //私有数据成员
    int m_nAge;                        //年龄
};
int main(int argc, char *argv[])
{
   Person *stu = new Student();    //基类使用派生类的构造器,基类类型的指针指向派生类对象
   stu->SetType();      //使用基类和派生类都实现的setType()函数测试真正调用的是哪一个
   return 0;
}

 

运行结果:

 结果说明了当使用虚函数继承机制的时候,会调用派生类中的函数,而不是基类。

2.特殊多态性函数:输入或输出参数在子类中是父类的指针或基类的引用,在子类中对于的是子类的指针或子类的引用:
void TestType(Person *p)    //传入的是基类的指针
{
    p->SetType();
}

void TestType(Person &p)    //传入的是基类的引用
{
    p.SetType();
}
int main(int argc, char *argv[])
{
    Person *stu = new Student();    //基类使用派生类的构造器,基类类型的指针指向派生类对象
   stu->SetType();      //使用基类和派生类都实现的setType()函数测试真正调用的是哪一个
    Person p1;
    Student s1;
    //TestType(p1);//调用void TestType(Person *p) 
    //TestType(s1);  //调用void TestType(Person *p) 

    TestType(&p1); //调用void TestType(Person *p) 
    TestType(&s1);//调用void TestType(Person *p)

    return 0;
}

运行结果:

 3.析构函数的多态性:

类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。

析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。

//析构函数
Person::~Person()
{
    cout<<"delete Person!"< 

运行结果:

 4.虚继承:

在多重继承中,如果发生了如:类B继承类A,类C继承类A,类D同时继承了类B和类C。最终在类D中就有了两份类A的成员,如下图:

 这在程序中是不能容忍的。当然解决这个问题的方法就是利用虚继承。

         虚继承的目的是让某个类做出声明,承诺愿意共享它的基类。其中,这个被共享的基类就称为虚基类(Virtual base Class),本例中的 A 就是一个虚基类。在这种机制下,不论虚基类在继承体系中出现了多少次,在派生类中都只包含一份虚基类的成员。因为在虚继承的最终派生类中只保留了一份虚基类的成员,所以该成员可以被直接访问,不会产生二义性。

class B: virtual public A{  //在基类前加virtual虚继承
protected:
    int m_b;
};

总结:

        在本次实验中,我进行了继承权限访问测试,友元类继承测试,多态性综合运用,初步学会了虚继承,用using语句提升继承的部分权限,友元类继承的相关概念和具体如何使用虚函数来实现函数多态性。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5116032.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-17
下一篇2022-11-17

发表评论

登录后才能评论

评论列表(0条)

    保存