C++学习之路 day7

Day7知识点:

1.类的继承,是新的类从已有类那里得到已有的特;类的派生,已有类产生新类的过程。原有的类称为基类父类,产生的新类称为派生类或子类

C++通过继承,来实现代码的重用性


继承的实验代码:


#include <iostream>

using namespace std;

#if 0
Inherit&Derive
学生 姓名,年龄,性别,学号,吃饭,学习
老师 姓名,年龄,性别,工号,吃饭,教学

        姓名,年龄,性别,吃饭           父类  基类
                                     继承  派生
学生:学号,学习      老师:工号,教学     子类  派生类;
#endif


class Human                 //父类    共性
{
public:
    void eat(string food)
    {
        cout<<"I am eating"<<food<<endl;
    }
};

class Student:public Human      //子类 是在父类的基础上增加新的功能,体现的是共性
{
public:
    void study(string course)
    {
        cout<<"I am a student , I am learning"<<course<<endl;
    }
};

class Teacher:public Human
{
public:
    void tech(string course)
    {
        cout<<"I am a teacher , I am teaching"<<course<<endl;
    }
};
int main()
{
    Student s;
    s.study("c++");
    s.eat("黄焖鸡米饭");

    Teacher t;
    t.tech("c++");
    t.eat("新疆大盘鸡");
    return 0;
}



2.关系定性is-a,has-a

is-a

狗是一种动物,动物是狗的基类,狗是动物的派生类。

A是B,B是A的基类,A是B的派生类。为继承关系


has-a

车有方向盘和轮胎,方向盘和轮胎是车的组成部分。

A包含B,B是A的组成部分。为聚合关系。



2.派生类的声明语法



class Son:public Father
{
public:
    int pub;
    void func()
    {
        x = 3;
        y = 4;
        z = 5;
    }
protected:
    int pro;
private:
    int pri;
};


3.第一个public为继承方式,第二个public为访问权限


继承方式public没有影响 子类的访问方式

影响了父类成员在子类的访问方式:

继承方式为公有继承public:在子类内,public和protected是可以访问的(通过子类函数),private不可访问(inaccess);

  :子类对象(子类外),只有public的可以访问。

假设father中有三种访问权限pub,pro,pri,在子类中分别为public,protected,inacess


public继承实验代码:

#include <iostream>

using namespace std;

class Father
{
public:
    int x;
protected:
    int y;
private:
    int z;

};

class Son:public Father
{
public:
    int pub;
    void func()
    {
        x = 3;
        y = 4;
//        z = 5;
    }
protected:
    int pro;
private:
    int pri;
};

//
int main()
{
    Son s;
    s.x = 0;
//    s.y = 0;
//    s.z = 0;
    return 0;
}




4.派生类对基类的接收


1.全盘接收除了构造器与析构器。可能造成派生类成员冗余,基类需要设计;

2.派生类有自己的个性才有意义。


5.派生类构造函数


Graduate::Graduate(string sn, int ia, float fs, double ds)
    :Student(sn,ia,fs),salary(ds)
{

}
class Father
{
public:
    Father(int i){}

};

class Son:public Father
{
public:
    Son():Father(4){}
};



派生类中如果有标配,重载或者默认,派生类中构造函数可以不用显示调用基类的构造器

class Father
{
public:
    Father(){}

};

class Son:public Father
{
public:
    Son(){}
};


子类只需对父类负责,不需要对父类的父类负责,父类的父类,由父类负责

class Father
{
public:
    Father(int i){}

};

class Son:public Father
{
public:
    Son(int j):Father(4){}
};

class Grandson:public Son
{
public:
    Grandson():Son(5){}
};


初始化顺序,先对父类初始化,在对类对象进行初始化,再完成本类的构造器

class A
{
public:
    A() 
    {
        cout<<"A"<<endl;    
    }
};

class Father
{
public:
    Father(int i)
    {
        cout<<"Father"<<endl;    
    }

};

class Son:public Father
{
public:
    Son(int j):Father(4)
    {
        cout<<"Son"<<endl;    
    }
};

class Grandson:public Son
{
public:
    Grandson(int k):Son(5)
    {
        cout<<"Grandson"<<endl;    
    }
    A a;
};

实验代码:

实验代码太长,在此不上传,代码文件名为 InheritSomeFunc






6.

a) 赋值兼容:子类对象(引用或指针),可以赋给父类对象(引用或指针)


b)子类未实现拷贝构造时,会默认调动父类的拷贝构造器。若子类有拷贝构造器,则必须显示调用父类拷贝构造器(因为继承不会继承构造器)。


c)子类中未实现赋值重载时,会调用父类的赋值重载(无论实现会未实现)。若子类实现了赋值重载,不会主动调用父类的赋值重载。


d) 子类中会把父类重名的成员shadow掉,函数名同即可构成shadow,与参数和返回值无关。


若非重名不可,则必须加上作用域运算符

#include <iostream>

using namespace std;

class Father
{
public:
    void dis()
    {

    }
};

class Son:public Father
{
public:
    void dis()
    {
        /*Father::*/dis();
    }
};

int main()
{
    Son son;
    son.dis();
    return 0;
}


实验代码:

//graduate.h
#ifndef GRADUATE_H
#define GRADUATE_H
#include "student.h"

class Graduate:public Student
{
public:
    Graduate(string sn, int ia, float fs,double ds);
    Graduate(const Graduate &another);
    Graduate& operator =(const Graduate &another);

    void print();
private:
    float salary;
};

#endif // GRADUATE_H

//student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
using namespace std;


class Student
{
public:
    Student(string sn,int ia,float score);
    Student(const Student& another);
    Student& operator =(const Student& another);

    void dis();
private:
    string name;
    int age;
    float score;
};

#endif // STUDENT_H
//graduate.cpp
#include "graduate.h"


Graduate::Graduate(string sn, int ia, float fs,double ds)
    :Student(sn,ia,fs),salary(ds)
{

}

Graduate::Graduate(const Graduate &another)
    :Student(another),salary(another.salary)
{

}

Graduate& Graduate::operator =(const Graduate &another)
{
    if(this == &another)
        return *this;
    Student::operator =(another);           //虽然继承父类的重载函数过来了,但由于命名冲突,不
                                            //能直接用,必须加命名空间
    this->salary = another.salary;

    return *this;
}

void Graduate::print()
{
    dis();
    cout<<"salary:"<<salary<<endl;
}
//student.cpp
#include "student.h"
#include <iostream>
using namespace std;

Student::Student(string sn , int ia,float fs)
    :name(sn),age(ia),score(fs)
{

}

Student::Student(const Student& another)
{
    name = another.name;
    age = another.age;
    score = another.score;
}

Student& Student::operator =(const Student& another)
{
    if(this == &another)
        return *this;
    this->name = another.name;
    this->age = another.age;
    this->score = another.score;
}

void Student::dis()
{
    cout<<"name:"<<name<<endl;
    cout<<"age:"<<age<<endl;
    cout<<"score:"<<score<<endl;
}
//main.cpp
#include <iostream>
#include "student.h"
#include "graduate.h"

extern int x=1;
using namespace std;

int main()
{
    Student s("zhaosi",34,150);
    s.dis();

    cout<<"-----------------------"<<endl;

    Graduate g("nengge",35,150,1200);
    g.print();

    cout<<"-----------------------"<<endl;

    Graduate gg("nhoioi",1,1,1);
    gg.print();
    gg = g;
    gg.print();

    return 0;
}









7.派生类析构顺序与构造顺序相反,子类->成员->基类。


#include <iostream>

using namespace std;

class A
{
public:
    A()
    {
        cout<<"A()"<<endl;
    }
    ~A()
    {
        cout<<"~A()"<<endl;
    }
};

class Base
{
public:
    Base()
    {
        cout<<"Base()"<<endl;
    }
    ~Base()
    {
        cout<<"~Base()"<<endl;
    }
};

class Derive:public Base
{
public:
    Derive()
    {
        cout<<"Drive()"<<endl;
    }
    ~Derive()
    {
        cout<<"~Derive()"<<endl;
    }
private:
    A a;
};

int main()
{
    Derive d;
    return 0;
}




8.

overload重载,同一作用域,函数名相同,参数列表不同(个数,类型,顺序)

shadow发生在父子类中,只要函数名相同,即可构成shadow


9.派生类的友元函数


实验代码:

#include <iostream>
using namespace std;


class Student
{
public:
    Student(int a, int b):
        _a(a),_b(b){}
    friend ostream &operator<<(ostream & out, Student & stu);
private:
    int _a;
    int _b;
};

ostream &operator<<(ostream & out, Student & stu)
{
    out<<stu._a<<"--"<<stu._b<<endl;
    return out;
}

class Graduate:public Student
{
public:
    Graduate(int a, int b, int c)
        :Student(a,b),_c(c){}
    friend ostream &operator<<(ostream & out, Graduate & gra);
private:
    int _c;

};

ostream &operator<<(ostream & out, Graduate & gra)
{
    cout<<static_cast<Student&>(gra);
    cout<<gra._c<<endl;

    return out;
}

int main()
{
    Student s(1,2);
    cout<<s;

    Graduate g(3,4,5);
    cout<<g;
}


 

10.继承方式

        public      public      public
pub     pub         pub         pub
pro     pro         pro         pro
pri     inaccess    inaccess    inaccess



        protected   protected   protected
pub     pro         pro         pro        
pro     pro         pro         pro
pri     inaccess    inaccess    inaccess    


        private     private     private 
pub     pri         inaccess    inaccess  
pro     pri         inaccess    inaccess         
pri     inaccess    inaccess    inaccess    



public 提供接口用(外部可以直接访问)传承了接口,也传承了数据
protected 隐藏数据用(外部只能通过成员函数访问)传承数据
private隐藏数据用(外部只能通过成员函数访问) 既没有传承接口,也没有传承数据


实验代码:

#include <iostream>

using namespace std;


class Base
{
public:
    int pub;
protected:
    int pro;
private:
    int pri;
};


class Derive:/*public*//*protected*/private Base
{
public:
    void func()
    {
//        pub = 100;
//        pro = 100;
        pub = 100;

    }
};

int main()
{
    Derive d;
//    d.pub = 100;



    return 0;
}




11.多继承
实验代码:
//bed.h
#ifndef BED_H
#define BED_H
#include <iostream>

using namespace std;

class Bed
{
public:
    Bed();
    void sleep();
};

#endif // BED_H
//sofa.h
#ifndef SOFA_H
#define SOFA_H
#include <iostream>

using namespace std;

class Sofa
{
public:
    Sofa();
    void sit();
};

#endif // SOFA_H
//sofabed.h
#ifndef SOFABED_H
#define SOFABED_H
#include "sofa.h"
#include "bed.h"

class SofaBed:public Sofa,public Bed
{
public:
    SofaBed();
};

#endif // SOFABED_H
//bed.cpp
#include "bed.h"

Bed::Bed()
{

}

void Bed::sleep()
{
    cout<<"go to bed and have a sleep"<<endl;
}
//sofa.cpp
#include "sofa.h"

Sofa::Sofa()
{

}

void Sofa::sit()
{
    cout<<"have a seat and have a sleep"<<endl;
}
//sofabed.cpp
#include "sofabed.h"

SofaBed::SofaBed()
{

}
//main.cpp
#include <iostream>
#include "sofa.h"
#include "bed.h"
#include "sofabed.h"

using namespace std;

int main()
{
    Sofa sf;
    sf.sit();

    Bed bed;
    bed.sleep();

    SofaBed sb;
    sb.sit();
    sb.sleep();



}

12.虚继承

将基类中的共同成员提取出来,只保留一份共同成员,在内存中只有基类成员的一份拷贝,被提取出来共同继承的类称为虚基类.

实验代码:

//funiture.h
#ifndef FUNITURE_H
#define FUNITURE_H


class Funiture
{
public:
    Funiture(float len, float wi, float we);

    void discript();

protected:
    float len;
    float wid;
    float weight;
};

#endif // FUNITURE_H
//bed.h
#ifndef BED_H
#define BED_H
#include <iostream>
#include "funiture.h"

using namespace std;

class Bed:virtual public Funiture
{
public:
    Bed(float len, float wi, float we);
    void sleep();


};

#endif // BED_H
//sofa.h
#ifndef SOFA_H
#define SOFA_H
#include <iostream>
#include "funiture.h"

using namespace std;

class Sofa:virtual public Funiture
{
public:
    Sofa(float len, float wi, float we);
    void sit();

};

#endif // SOFA_H
//sofabed.h
#ifndef SOFABED_H
#define SOFABED_H
#include "sofa.h"
#include "bed.h"
#include "funiture.h"

class SofaBed:public Sofa,public Bed
{
public:
    SofaBed(float len, float wi, float we);
};

#endif // SOFABED_H
//funiture.cpp
#include "funiture.h"
#include <iostream>

using namespace std;

Funiture::Funiture(float len, float wi, float we)
    :len(len),wid(wi),weight(we)
{

}


void Funiture::discript()
{
    cout<<"len = "<<len<<endl;
    cout<<"wid = "<<wid<<endl;
    cout<<"weight = "<<weight<<endl;
}
//bed.cpp
#include "bed.h"

Bed::Bed(float len, float wi, float we)
    :Funiture(len,wi,we)
{


}

void Bed::sleep()
{
    cout<<"go to bed and have a sleep"<<endl;
}
//sofa.cpp
#include "sofa.h"

Sofa::Sofa(float len, float wi, float we)
    :Funiture(len,wi,we)
{

}

void Sofa::sit()
{
    cout<<"have a seat and have a sleep"<<endl;
}
//sofabed.cpp
#include "sofabed.h"

SofaBed::SofaBed(float len, float wi, float we)
    :Funiture(len,wi,we),Bed(len,wi,we),Sofa(len,wi,we)
{

}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值