C++学习day22之继承与派生

时间:2022-12-15 13:17:40
 
#include<iostream>

using namespace std;

/*
 *类内部的private protected public 影响的访问权限
 *继承中的private protected public 影响的是父类中的成员在子类中的访问权限的 问题  这个访问权限包括两部分。1.在子类中 2.在子类对象中。
 *99%情况下只是用public继承方式。
 *
 *为什么这么说呢,假设我现在有个类 里面有个成员是public pub,protected成员
 *pro,private成员 pri。我public继承之后,你以前是public的,还是public,你是
 *private,你在子类里面就变成不可访问的了,你是protected还是protected。
 *
 * 你如果是protected继承的话,你父类中的public在子类中就变成了protected,
 * 你的protected变成了protected,但是你的private还是跟上面一样的,不能访问
 *
 *
 * 你如果是private继承的话,他public和protected都变成private了,这就说明你在子类内部还是可以访问,但是private还是不能访问
 */ 


/*所以说
 * public 提供传承接口用的。因为你public传承下去,public和protected都可以被传承下去,
 * privatre 提供隐藏数据用的。中间还有一个protected,protected可以隐藏数据还能传承数据。
class Base
{
public:
    int pub;
protected:
    int pro;
private:
    int pri;
};

class Deriver:private Base
{
public:
    void dis()
    {
        pro=100;
        pub=200;
    }
    int x;
protected:
    int y;
protected:
    int z;
};

int main()
{
/*1.这样肯定会报错,因为这个y,z都是被保护的数据
    Deriver a;
    a.x=100;
    a.y=100;
    a.z=100;
*/
}



#include<iostream>
using namespace std;
class Student
{
public: 
Student(string sn,int ia,float fs) 
    :name(sn),age(ia),score(fs) 
    { 
    } 
    void dis() 
    { 
        cout<<name<<endl; 
        cout<<age<<endl; 
        cout<<score<<endl; 
    }
private: 
    string name; 
    int age; 
    float score;
};
class Graduate:public Student
{
    public: Graduate(string sn,int i,float fs,double sa=1000)
        :Student(sn,i,fs),salary(sa) 
    { 
    } 
    /*你加这个拷贝构造器会报错,你不加这个不会报错,浅拷贝*/ 
    /*因为子类会调用父类的构造器*/
    Graduate(const Graduate &another) 
    { } 
    void display() 
    { dis(); cout<<salary<<endl; }
 private: 
    double salary;
};
int main()
{ 
    Student s("zhaosi",34,150); 
    s.dis(); 
    Graduate g("nengge",40,200); 
    //g.display(); 
    Graduate f(g); 
    f.display();
}



#include<iostream>
using namespace std;

class Student
{
public:
    Student(string sn,int ia,float fs)
        :name(sn),age(ia),score(fs)
    {
    
    }
    Student(const Student & another)
    {
        this->name=another.name;
        this->age=another.age;
        this->score=another.score;
    }
    void dis()
    {
        cout<<name<<endl;
        cout<<age<<endl;
        cout<<score<<endl;
    }

private:
    string name;
    int age;
    float score;
};

class Graduate:public Student
{
public:
    Graduate(string sn,int i,float fs,double sa)
        :Student(sn,i,fs),salary(sa) 
    {
    
    
    }
    /*你加这个拷贝构造器会报错,你不加这个不会报错,浅拷贝*/
    /*因为子类会调用父类的构造器*/
    /*子类未实现拷贝构造的时候,会调用父的拷贝构造器(无论实现与否)
     * 这句话的理解就是你可以把子类graduate的拷贝拷贝构造器注释掉
     * 不会报错
     * 子类一旦实现了拷贝构造,则必须显示的父类的拷贝构造器*/
    Graduate(const Graduate &another)
        :Student(another)
    {
    /*赋值兼容(子类对象(引用或者指针),可以赋给父类对象(引用或指针)
     * 这里其实发生了隐式类型转换*/
    //这里只会拿前面3个空间拷贝过去*/
          
        /*这里不能放在这里,因为拷贝构造器是不能被继承的
        Student(another);*/
          this->salary=another.salary
#include<iostream>
using namespace std;

class Student
{
public:
    Student(string sn,int ia,float fs)
        :name(sn),age(ia),score(fs)
    {
    
    }
    Student(const Student & another)
    {
        this->name=another.name;
        this->age=another.age;
        this->score=another.score;
    }
    Student &operator=(const Student & another)
    {
        this->name=another.name;
        this->age=another.age;
        this->score=another.score;
        return *this;
    }
    void dis()
    {
        cout<<name<<endl;
        cout<<age<<endl;
        cout<<score<<endl;
    }

private:
    string name;
    int age;
    float score;
};

class Graduate:public Student
{
public:
    Graduate(string sn,int i,float fs,double sa)
        :Student(sn,i,fs),salary(sa) 
    {
    
    
    }
    /*你加这个拷贝构造器会报错,你不加这个不会报错,浅拷贝*/
    /*因为子类会调用父类的构造器*/
    /*子类未实现拷贝构造的时候,会调用父的拷贝构造器(无论实现与否)
     * 这句话的理解就是你可以把子类graduate的拷贝拷贝构造器注释掉
     * 不会报错
     * 子类一旦实现了拷贝构造,则必须显示的父类的拷贝构造器*/
    Graduate(const Graduate &another)
        :Student(another)
    {
    /*赋值兼容(子类对象(引用或者指针),可以赋给父类对象(引用或指针)
     * 这里其实发生了隐式类型转换*/
    //这里只会拿前面3个空间拷贝过去*/
          
        /*这里不能放在这里,因为拷贝构造器是不能被继承的
        Student(another);*/
          this->salary=another.salary;
    }
    Graduate & operator=(Graduate &another)
    {
        if(this==&another)
            return *this;
        else
        {
            /*但是这里operator=这个父子类重名*/
            Student::operator=(another);
            this->salary=another.salary;    
        }
        return *this;
    }
    void display()
    {
        dis();
       cout<<salary<<endl;
    }
private:
    double salary;
};

int main()
{
    Student s("zhaosi",34,150);
    s.dis();
    Graduate g("nengge",40,200,1000);
    //g.display();
    Graduate f(g);
    Graduate gg("11",1,1,1);
    /*第一步:这里没问题,前面没有显示写出赋值运算符重载的时候,说明这里
     * 面含有默认*/
    /*第二步:我们实现父类的运算符重载
     * 子类中未实现赋值重载时,会调用父类的赋值重载(无论实现与否)
     * 子类一旦实现赋值重载,不会调用父类的赋值重载了。
     * Student & operator=(const Student& another)*/
    gg=f;
    f.display();
    gg.display();
}

#include<iostream>
using namespace std;

class Father
{
public:
    void dis()
    {
        
    }
};

class Son:public Father
{
public:
    void dis()
    {
        /*我这里的逻辑是我这里的dis调用父类的dis,父子类重名就会出现
         * shadow,shadow就是阴影的意思,就是子类中会把父类重名成员给shadow掉
         覆盖之后他就认为父类中没有这个东西了,这里他就会自己调用自己。 
         所以它会一直递归下去,没有尽头。
         dis();
         shadow只跟函数名有关,跟你有没有参数没有关系,跟返回值没关
         你int dis()和void dis()是一样的,你int dis(int) 和int dis()也是一样的
        */
        /*所以这个时候只能用命名空间*/
        Father::dis();
    }
};
int main()
{

}

#include<iostream>

using namespace std;
/*
 *重载:发生在同一个作用域,函数名相同,参数列表不同
 *     参数列表不同包括个数,类型和顺序。有一个或一个以上满足都会构成重载
 *shadow:发生在父子类中,爷爷类和孙子类之间也可以。只要函数名相同即可构成shadow。
 *一般来说,重载是我们希望看到的,因为重载可以给我们带来很多方便。但是shadow是我们不希望发生的,尽量不要写shadow重名函数。发生了需要用命名空间来解决这个问题
 *
 */
int main()
{

}