C++第八节课

C++第八节课,第1张

C++第八节课

1.继承

继承的实质就是父类的数据子类成员中有一份

继承方式只会增强父类在子类中的权限显示

任何方式的继承子类都不能直接访问父类的私有属性,但可以通过父类留下的公有接口访问数据

#include
#include
using  namespace std;
class Fox
{
public:
    Fox(string name,int money):name(name),money(money) {}//构造函数
    int& retunmoney() 
    {
        return this->money;
    }
    void  print() 
    {
        cout << name << money << endl;
    }
protected:
    string name;
private:
    int money;
};
class Son :public Fox //公有继承
{
public:
    void print() 
    {
       //cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
        cout < 

1.2 关于继承的权限问题:任何继承方式都不可以访问父类的私有属性

                                          

继承后属性提升问题protected继承protectedprotected不可直接访问public继承publicprotected不可直接访问private继承privateprivate不可直接访问

知识点:当子类用私有继承父类属性后  会导致父类中的保护属性变成子类的私有属性

子类是可以访问该私有属性,但是通过子类再次继承子类之后(我们称为孙子类)

会导致孙子类无法访问任何一个属性

#include
#include
using  namespace std;
class Fox
{
public:
    Fox(string name,int money):name(name),money(money) {}//构造函数
    int& retunmoney() 
    {
        return this->money;
    }
    void  print() 
    {
        cout << name << money << endl;
    }
protected:
    string name;
private:
    int money;
};
class Son :public Fox //公有继承
{
public:
    void print() 
    {
       //cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
        cout < 

2.继承中构造函数的写法

 父类的数据必须由父类的构造函数初始化

 子类中构造函数,必须调用父类自己的构造函数,并且使用参数列表的方式(这里指的是构造父类的情况),自己的属性初始化随便写

 单继承和多继承 

  单继承:只有一个父类

  多继承:两个或以上的父类

单继承

#include
#include
using  namespace std;
class Fox
{
public:
    
    Fox(string name,int money):Fname(name),money(money) {}//构造函数
    int& retunmoney() 
    {
        return this->money;
    }
    void  print() 
    {
        cout << Fname << money << endl;
    }
protected:
    string Fname;
private:
    int money;
};
class Son :public Fox //公有继承
{
public:
    void print() 
    {
       //cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
        cout <Sname = Sname;
        this->sonmoney = sonmoeny;
    }
protected:
    string Sname;

private:
    int sonmoney;
};
class Son1:protected Fox //保护继承
{
 public:
   
     Son1(string Fname,int money,string Sname,int sonmoeny) :Fox(Fname, money) //利用参数初始化列表初始化父类构造函数
     {   //子类初始话方式随便
         this->Sname = Sname;
         this->sonmoney = sonmoeny;
     }
     void print()
    {
        //cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
        //cout << Fname << endl;
        //cout << Fox::retunmoney() << endl;//可以通过父类留下的公有接口访问父类的私有属性
        cout << Sname << sonmoney << endl;
        cout << Fname << Fox::retunmoney() << endl;
    }

protected:
    string Sname;

private:
    int sonmoney;
};
class Son2:private Fox //私有继承
{
public:
    void print()
    {
        //cout << money << name << endl;//错误写法 任何继承子类都无法通过自身权限访问父类的私有属性
        cout << Fname << endl;
    }
protected:

};
class Grandson :public Son2   //继承私有继承的子类
{
    void print()
    {
       
      //  cout << name << endl;//上一个子类中所有属性都为保护属性,当前类无法访问任何一个数据
    }
};

int main() 
{

    Son1 Foxson("狐狸",18,"狐狸儿子",0);
    Foxson.print();

    
    return 0;
}

多继承:

#include
#include
using namespace std;
class FoxM
{

public:
    FoxM(string name, int age) :Mname(name), Mage(age) {}
    

protected:
    string Mname;
    int Mage;
};
class FoxF
{
public:
    FoxF(string name, int age) :Fname(name), Fage(age) {}
protected:
    string Fname;
    int Fage;
};
class FoxSon :public FoxM, public FoxF //多继承
{
public:
    FoxSon(string Mname, int Mage, string Fname, int Fage)
        :FoxF(Mname, Mage), FoxM( Fname,Fage)//初始化参数列表
    {
        this->SonName = "小狐狸";
        this->Sonage = 18;
        
    }
    void pring()
    {
        cout << Mname << Mage << endl;
        cout << Fname << Fage << endl;
        cout << SonName << Sonage << endl;
    }
protected:
    string SonName;
    int Sonage;
};

int main() 
{   
    FoxSon fox1("母狐狸",15,"大狐狸",12);
    fox1.pring();

    return 0;
}

3.关于继承中同名的问题

  • 数据成员同名

  • 成员函数名同名

  • 正常赋值调用

  • #include
    #include
    using namespace std;
    class Fox1
    {
    public:
        Fox1(string name,int age):name(name),age(age) {}
        void printf() 
        {
            cout << name << age<name = "狐狸";
            this->age = 3;
        }
        void printf() 
        {
            cout << name << age << endl;//就近原则 在继承中 出现同名行为或者数据 都是就近原则
            Fox1::printf();//可以使用类名限定的方式去访问
            cout << Fox1::name << Fox1::age << endl;//可以使用类名限定的方式去访问
        }
         
    protected:
        string name;
        int age;
    };
    int main() 
    {    Fox2* pFox2 =new Fox2("狐狸123",5);
        pFox2->printf();//优先调用自己子类中的同名函数
        pFox2->Fox1::printf();//通过类名限定调用父类中的同名函数
    
        return 0;
    }

  • 非正常赋值调用

  • 允许子类对象填充父类指针

  • int main() 
    {   
        //非正常调用 
        Fox1* PFox1 = new Fox2("狐狸",3);
        PFox1->printf();//优先调用指针类型的函数,也就是调用父类中的成员函数
        return 0;
    }

    菱形构造的问题

  • 所谓菱形构造问题就是 一个父类产生单独的两个子类,都继承了父类的数据成员

  • 当两个子类又再次多继承出来一个子类 会导致构造函数中出现相同的数据成员

  • virtual关键字避免了该情况的发生,用virtual修饰子类,出现菱形继承时,默认使用最构造父类的构造函数初始父类中的数据成员,有效的避免了产生相同的数据成员问题

  • #include
    #include
    using namespace std;
    //继承的属性一致都存在
    class A
    {
    public:
    	A(int a) :a(a) {}
    protected:
    	int a;
    };
    class B :virtual public A
    {
    public:
    	B(int a, int b) :A(a), b(b) {}
    protected:
    	int b;
    };
    class C :virtual public A
    {
    public:
    	C(int a, int c) :A(a), c(c) {}
    	void printC()
    	{
    		cout << a << endl;
    	}
    protected:
    	int c;
    };
    class D :public C, public B
    {
    public:
    	//菱形继承,必须调用祖父的构造函数
    	D() :B(100, 200), C(300, 400), A(1011)
    	{
    
    	}
    
    	void printf1()//A为1011 使用最开始父类的值
    	{
    		//只有一个a 只有一份
    		cout << a << endl;
    		cout << B::a << endl;
    		cout << C::a << endl;
    		printC();
    	}
    protected:
    
    };
    

    析构问题

  • 构造顺序和参数初始化列表的顺序无关,构造顺序和继承顺序一致

  • 析构是反过来的

    #include
    #include
    #include 
    using namespace std;
    class A
    {
    public:
    	A() { cout << "A"; }
    	~A() { cout << "A"; }
    protected:
    };
    class B :public A
    {
    public:
    	B() { cout << "B"; }
    	~B() { cout << "B"; }
    };
    
    class C
    {
    public:
    	C() { cout << "C"; }
    	~C() { cout << "C"; }
    };
    class D
    {
    public:
    	D() { cout << "D"; }
    	~D() { cout << "D"; }
    };
    //构造顺序和继承顺序一致
    class F :public C, public A, public D
    {
    public:
    	//任何构造顺序问题,都和初始化参数列表无关
    	F() { cout << "F"; }
    	~F() { cout << "F"; }
    };
    int main()
    {
    	{
    
    		B b;   //ABBA 
    	}
    	cout << endl;
    	F f;//C A D F F D A C //
    	return 0;
    }

    作业:

  • 实现形状类的继承

  • #include
    #include
    using namespace std;
    class Shape
    {
    public:Shape(string form="",double length = 0.0, double breadth = 0.0, double radius = 0.0) {}//缺省方式
    
    	
    protected:
        double length;//长度
        double breadth;//宽度
        double radius;//半径
        string form;//形状
    };
    class Rect :public Shape
    {
    public:
           Rect(string form, double radius, double breadth=0.0, double length=0.0) :Shape(form, length, breadth, radius) 
           {
               this->perimeter = radius * 2 * 3.14; 
               this->area = 3.14 * radius * radius;
           }
          void printf() 
          {
              cout << "形状是" << "t" << Shape::form << "面积是" << area << "周长是" << perimeter;
          }
    private:
    
        double perimeter;
        double area;
    };
    class Circle :public Shape
    {
    public:
        Circle(string form, double radius=0.0, double breadth = 0.0, double length = 0.0) :Shape(form, radius, breadth, length)
        {
            this->perimeter = (breadth + length) * 2;
            this->area = breadth * length;
        }
        void printf()
        {
            cout << "形状是" << "t" << Shape::form << "面积是" << area << "周长是" << perimeter;
        }
    private:
    
        double perimeter;
        double area;
    };
    
    int main()
    {
    
        Rect testpact("圆形", 5);
        testpact.printf();
        Circle testcircle("长方形",0.0,5,10);
        testcircle.printf();
        return 0;
    }

    作业2:多名老师为父类的研究生类:

#include
#include
using namespace std;
class Teacher
{

public:Teacher(string name):Tname(name)
{

}

protected:
  string Tname;
};
class Student
{

public:Student(string Sname) :Sname(Sname) {}

protected:
    string Sname;
}; 
class Graduate:public Teacher, Student//继承老师类和学生类
{

public:
     Graduate(string Sname, string Tname) :Teacher(Tname), Student(Sname) {}
      void printf() 
      {
          cout << "该研究生名:" << Sname << "t" << "老师名" << Tname << endl;
      }
protected:
   
};


int main()
{
    Graduate fox("小狐狸", "莫大帅");
    fox.printf();
    return 0;
}

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

原文地址: https://outofmemory.cn/zaji/5650403.html

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

发表评论

登录后才能评论

评论列表(0条)

保存