2024寒假学习c++进入封装与继承

#include <iostream>
#include <string>
using namespace std;
const double PI = 3.14;

初识封装类与对象

//第一个
//
//class circle {
//    public://公共的访问权限
//        //属性
//        int r;
//        //行为
//        double calculate() {
//            return 2 * PI * r;
//        }
//
//};
//
//int main() {
//    circle cl;
//    cl.r = 10;
//    cout << "圆的周长" << cl.calculate() << endl;
//}
//第二个
//class Student {
//    public:
//        string name;
//        int number;
//        void showstudent() {
//            cout << "学生的姓名" << name << "学生的学号" << number << endl;
//        }
//        void setstudent(string my_name){
//            name=my_name;
//        }
//};
//
//int main() {
//    Student zyc;
//    cout << "请输入学生姓名与学号" << endl;
//    cin >> zyc.name >> zyc.number;
//    zyc.showstudent();
//    zyc.setstudent("张宇超");//赋值函数,行为给属性赋值
//
//    Student zbc;
//    cout << "请输入学生姓名与学号" << endl;
//    cin >> zbc.name >> zbc.number;
//    zbc.showstudent();
//}

三个访问方式


//第三个
//访问权限 public   公共权限类内类外都可访问
//         protected公共权限类内可以 类外不可,儿子可以访问
//         private公共权限类内可以 类外不可,儿子不可以访问,类外就是在calss之外的

//struct与class访问权限不同,struct默认权限工共,class默认私有


//private的意义可读可写的控制,用public的方法来处理
//class student {
//    public:
//        void showfood() {
//            cout << food << endl;
//        }
//        void setfood(string a_food) {
//            food = a_food;
//        }
//        void showage() {
//            cout << "学生年龄为" << age << endl;
//        }
//        void setage() {
//            cout << "请输入年龄" << endl;
//            cin >> age;
//            if (age < 0 || age > 150) {
//                cout << "你输入的年龄有误" << endl;
//                return ;
//            }
//
//        }
//        void setlove(string a_love) {
//            love = a_love;
//        }
//    private:
//        string food;//可读可写
//        int age = 18 ; //可读
//        string love;//可写
//};
//
//int main () {
//
//    student p;
//    p.setfood("宫保鸡丁");//可写的设置
//    p.showfood();//可读的设置
//    p.setage();
//    p.showage();
//    p.setlove("张宇超");
//}

构造函数,析构函数


构造函数,析构函数,他们不要返回值,没void,不写的话系统自己整2个,函数名与类名一致,构造函数可以有参数,析构函数不可以有参数名字前有~来区分两个
分类:1有参无参2普通构造,拷贝构造
//class person {
//    public:
//        person() {
//            cout << "无参构造函数" << endl;
//        }
//        person(int a,int height) {
//            cout << "有参构造函数" << endl;
//            age = a;
//            m_height=new int(height);//堆区
//        }
//        person(const person &p) {
//            cout << "拷贝构造函数" << endl;
//            age = p.age;//浅拷贝
//            m_height=new int(*p.m_height);//深拷贝
//        }
//        ~person() {
//            //将堆区开辟的数据释放
//            if(m_height!=NULL){
//                delete m_height;
//                m_height=NULL;
//            }
//
//
//
//            cout << "析构函数" << endl;
//        }
//
//        int age;
//        int *m_height;
//
//};
值的方式传数据,值的方式返回都会调用拷贝构在函数
//int main() {
//    person p;//注意调用默认构造不能加()
//    person p2(10);
//    person p3(p2);
//}
创建一个类,系统默认给三个函数给、拷贝,析构,默认
如果写了有参构造,系统自己给拷贝,不给默认
如果写了拷贝,有参,默认都不提供


//
初始化列表


//class person {
//    public:
//        person(int a, int b, int c): m_A(a), m_B(b), m_C(c) {
//        }
注意冒号
//        void show() {
//            cout << "m_A:" << m_A << endl;
//        }
//    private:
//        int m_A;
//        int m_B;
//        int m_C;
//
//};
//
//int main () {
//    person p(1, 2, 3);
//    p.show();
//}

静态成员变量:

不属于某个对象(实例)所有对象共享同一个数据,类内声明类外初始化,编译阶段分配内存
//静态成员函数:所有对象共享同一个函数,并且只能访问静态成员变量
//class person {//他们两个必须public,存在访问权限,private不行
//    public:
//        static int m_a;
//        static void func(){
//            m_a=3000;//可以访问静态成员
//            cout<<"静态函数的调用"<<endl;
//        }
//};
//int person:: m_a = 100; //类外初始化
//
//void test01() {
//    person p;
//    cout << p.m_a << endl;
//    person p2;
//    p2.m_a = 200;
//    cout << p.m_a << endl; //200结果
//}
//
//void test02() {
    访问方式2种,通过对象;通过类名
//    person p2;
//    p2.func();
//    cout << p2.m_a << endl;
//
//    person::func();
//    cout << person::m_a << endl;
//}
//
//int main() {
//    test01();
//    test02();
//}

成员变量成员函数分开存储,只有非静态成员属于类的对象上
空对象占用内存空间1,因为要区分不同的空对象占内存位置,不能沾重复位置
//class person {
//    public:
//        //    int m_a;//非静态成员,属于类的对象上
//        static int m_b;//静态成员和函数,不属于类的对象上
//};
//int person::m_b;
//
//int main () {
//    person p;
//
//    cout << "sizeof(p)为" << sizeof(p) << endl;
    cout << "sizeof(m_a)为" << sizeof(p.m_a) << endl;
//    cout << "sizeof(m_b)为" << sizeof(p.m_b) << endl;
//}
//


this指针

解决名称冲突(形参与成员属性区分),返回对象本身
//class person {
//    public:
//        person(int age) {
//            this ->age = age;//this指针指向的是谁掉的有参构造,就指向谁
//        }//这里指向P
//        void personaddage(person p) {
//            this->age += p.age;
//        }
//        person& personaddage1(person p) {//&是引用,返回的是一个对象,如果不加每次返回的都是新的,从而无法实现累加
//            this->age += p.age;
//            return *this;//this是指向p的指针,加*就成了本体,实现链式编程
//        }
//        int age;
//};
//
//int main() {
//    person p(10);
//    person p1(10);
//    p1.personaddage(p);
//    cout << "p1的年纪是" << p1.age << endl;
//    p1.personaddage1(p).personaddage1(p).personaddage1(p);
//    cout << "现在p1的年纪是" << p1.age << endl;
//     cout << p.age << endl;
//}

空指针问题


//if(this==NULL){
//    return;
//}

常函数


//class person{
//    public:
//        void showperson()
//        {
//            m_a=100;
//        }
//        int m_a;
//};
//int main(){
//
//}

友元


全局函数佐友元,能够访问私有
//class Building {
//        friend void goodgay(Building *p);
//    public:
//        Building() {
//            m_sittingroom = "客厅";
//            m_bedroom = "卧室";
//        }
//        string m_sittingroom;
//    private:
//        string m_bedroom;
//
//};
//
//void goodgay(Building *p) {
//    cout << "好友在访问" << p->m_sittingroom << endl;
//    cout << "好友在访问" << p->m_bedroom << endl;
//}
//
//int main() {
//    Building p;
//    goodgay(&p);
//}


//类做友元
//class  Building {
//        friend class Goodgay;
//    public:
//        Building() {
//            this->m_sittingroom = "餐厅";
//            this->m_bedroom = "卧室";
//
//        }
//        string m_sittingroom;
//    private:
//        string m_bedroom;
//};
//
//class Goodgay {
//    public:
//        Goodgay() {
//            building = new Building;
//        }
//        void visit() {
//            cout << "好基友正在访问" << building->m_sittingroom << endl;
//            cout << "好基友正在访问" << building->m_bedroom << endl;
//        }
    private:
//        Building *building;
//};
//
//
//void test01() {
//    Goodgay gg;
//    gg.visit();
//}
//
//int main() {
//
//    test01();
//}


运算符重载


加号,实现两个类相加
//class person {
//    public:
        //方式1、成员函数内部重载
        person operator+(person &p) {
            person temp;
            temp.m_a = this->m_a + p.m_a;
            temp.m_b = this->m_b + p.m_b;
            return temp;
        }
//        int m_a;
//        int m_b;
//};
//
方式二,全局函数重载+号
//person operator+(person &p1, person &p2) { //最前面o\person,是返回值类型
//    person temp;
//    temp.m_a = p1.m_a + p2.m_a;
//    temp.m_b = p1.m_b + p2.m_b;
//    return temp;
//}
//
//person operator+(person &p1, int num) {
//    person temp;
//    temp.m_a = p1.m_a + num;//两个函数名字一样,参数不同,叫函数重载
//    temp.m_b = p1.m_b + num;
//    return temp;
//}
//
//void test01() {
//    person p1;
//    p1.m_a = 10;
//    p1.m_b = 10;
//    person p2;
//    p2.m_a = 10;
//    p2.m_b = 10;
//    person p3 = p1 + p2;
//    cout << "p3.m_a是" << p3.m_a << endl;
//    cout << "p3.m_b是" << p3.m_b << endl;
//    person p4 = p1 + 100;
//    cout << "p4.m_a是" << p4.m_a << endl;
//    cout << "p4.m_b是" << p4.m_b << endl;
//}
//
//int main () {
//    test01();
//}

//左移运算符重载,只能用全局函数,现在目的输入对象本身,输出全部属性
//class person {
//        friend ostream &operator<<(ostream &cout, person &p); //这样可以访问private;
//    public:
//        person(int a, int b) {
//            m_a = a;
//            m_b = b;
//        }
//        int m_a;
//        int m_b;
//};
//
//ostream &operator<<(ostream &cout, person &p);
//
//void test01() {
//    person p(10, 10);
    p.m_a = 10;
    p.m_b = 10;
//
//    cout << p << "hello" << endl;
    cout << p;想在后面继续添加,就使用链式思想,不断返回对象本身
//}
//
//ostream &operator<<(ostream &cout, person &p) {
//    cout << "m_a=" << p.m_a  << "m_b=" << p.m_b << endl;
//    return cout;
//}
//
//int main() {
//    test01();
//
//}

重载运算符,实现自己写一个int
//class Myinteger {
//        friend ostream &operator<<(ostream &cout, Myinteger myint);
//    public:
//        Myinteger() {
//            m_num = 0;
//        }
//    private:
//        int    m_num;
//};
//
此函数处理<<输出自己int的数据
//ostream &operator<<(ostream &cout, Myinteger myint) {
//    cout << myint.m_num;
//    return cout;
//}
//
重载前置运算符++a
//Myinteger &operator++() {
//    m_num++;//先进行++运算
//    return *this;//前置返回自身
//}
//
//
Myinteger operator++(){
    m_num++;//先进行++运算
    return *this;//返回自身
}如果返回值不加引用,在++的基础上在做++每次返回是新值,最终返回该数据只是加了一次的数据
重载后置运算符a++,这里函数重载出问题,不可以用返回值不同区分函数
//Myinteger operator++(int) { //这里加int表示占位参数,用于区分前置与后置
//    //先返回
//    Myinteger temp = *this; //记录当前的值,然后让本身加1,但是返回的是以前的值m_num++;
//    //后++
//    m_num++;
//    return temp;//后置返回值
//}
//
//void test01() {
//    Myinteger myint;
//    cout << myint << endl;
//    cout << ++myint << endl;
//    cout << myint++ << endl;
//}
//
//
//
//int main() {
//    test01();
//}


//赋值运算符重载
//class person {
//    public:
//        person(int age) {
//            m_age = new int(age);//数据创建在堆区,手动开辟
//        }
//        ~person() {
//            if (m_age != NULL) {
//                delete m_age;
//                m_age = NULL;
//            }
//        }
//        int *m_age;
//};
//
//person &operator=(person &p) {
//    //编译器提供浅拷贝
    this->m_age=p.m_age
应先判断是否有属性在堆区,如果有先释放干净再深拷贝
//    if (m_age != NULL) {
//        delete m_age;
//        m_age = NULL;
//    }
深拷贝
//
//    m_age = new int(*p.m_age);
返回对象本身
//    return*this;
//}
//
//void test01() {
//    person p1(18);
//    person p2(20);
//    person p3(30);
//    p2 = p1;
//    cout << "p1的年龄是" << *p1.m_age << endl;
//    cout << "p2的年龄是" << *p2.m_age << endl;
//    //连续时,要返回对象本身
//    p3 = p2 = p1;
//}
//
//int main () {
//
//    test01();
//}

//关系运算符重载
//class person {
//    bool operator==( person &p) {
//    if (this->m_name == p.m_name && this->m_age == p.m_age) {
//        return true;
//    } else {
//        return false;
//    }
//}
//    public:
//        person(int age, string name) {
//            m_age = age;
//            m_name = name;
//        }
//        int m_age;
//        string m_name;
//};
//int main () {
//    person p1(10, "tom");
//    person p2(20, "jerry");
//    if (p1 == p2) {
//        cout << "相等" << endl;
//    } else {
//        cout << "不相等" << endl;
//    }
//}


//函数调用运算符重载,仿函数灵活多变,没固定格式
//class Myprint {
//    public:
//        void operator()(string a) {
//            cout << a << endl;
//        }
//        int operator()(int num1, int num2) {//函数重载
//            return num1 + num2;
//        }
//};
//int main() {
//    Myprint myprint;
//    myprint("张宇超");
//    cout << myprint(100, 200) << endl;
//}

继承

//继承:class 子类/派生类:继承方式 父类/基类
//class BasePage {
//    public:
//        void head() {
//            cout << "首页,公开课" << endl;
//        }
//        void foot() {
//            cout << "交流中心,互助" << endl;
//        }
//
//
//};
//
//class java: public BasePage {
//    public:
//        void content() {
//            cout << "java学科视频" << endl;
//        }
//
//};
//
//class cpp: public BasePage {
//    public:
//        void content() {
//            cout << "c++学科视频" << endl;
//        }
//
//};
//
//int main() {
//    //java页面
//    cout << "java如下" << endl;
//    java ja;
//    ja.content();
//    ja.foot();
//    ja.head();
//    cout << "-------------- " << endl;
//    //cpp页面
//    cout << "c++如下" << endl;
//    cpp cp;
//    cp.content();
//    cp.foot();
//    cp.head();
//    cout << "-------------- " << endl;
//}
继承方式,
//class A{
//    public:int a;
//    protected: int b;
//    private: int c;
//};
公有继承
//class B:public A{
//    public:int a;
//    protected:int b;
//    //父类中私有不可访问
//};
保护继承
//class B:protected A{
//    protected:int a;
//              int b;
// //父类中私有不可访问
//};
私有继承
//class C:private A{
//    private:int a;
//    int b;
//    //父类中私有不可访问
//};


//父类的属性都属于子类,只是private无法访问
//打开vs的开发人员命令提示符
//盘名称:\cd 文件路径
//下一行写dir
//最后cl /d1 reportSingleClassLayout查看的类名 所属文件夹(tap自动补全)

//继承中构造析构顺序
//直接调用son s;
//父类构造,子类构造,子类析构,父类析构

//继承中同名成员处理方式
//class Base{
//    public:
//        Base(){
//            m-a=100;
//        }
//        int m-a;
//};
//class son:public Base{
//    public:
//        son(){
//            m-a=200;
//        }
//        int m-a;
//};
//int main(){
//    son s;
//    //字类对象直接访问子类成员
//    cout<<"son下的m-a等于"<<s.m_a<<endl;
//    //通过子类对象访问父类中同名,要加作用域 Base::,成员函数同名,子类会隐藏父类同名函数,必须要加作用域,不管有没有参数
//    cout<<"base下的m-a等于"<<s.Base::m_a<<endl;
//}


//继承中同名静态成员处理方式,与非静态差不多,只不过多出一种类名直接访问
//首先,静态成员特点:1数据属于类,所有对象共享2编译分配内存3类内声明类外初始化
//静态函数只能调用静态成员,子类同名函数会隐藏所有父类同名,无论是否重载,调父类都必须加作用域
//class Base {
//    public:
//        static int m_a;
//        static void func() {
//            cout << "Base static void func()的访问";
//        }
//};
//int Base::m_a = 100;
//
//class son: public Base {
//    public:
//        static int m_a;
//        static void func() {
//            cout << "son static void func()的访问";
//        }
//};
//int son::m_a = 200;
同名静态成员属性
//void test01() {
//    //1~通过对象访问
//    son s;
//    cout << "通过对象" << endl;
//    cout << "son下的m_a" << s.m_a << endl;
//    cout << "Base下的m_a" << s.Base::m_a << endl;
//    //2`通过类名访问
//    cout << "通过类名" << endl;
//    cout << "son下的m_a是" << son::m_a << endl;
//    cout << "直接访问Base类的m_a是" << Base::m_a << endl;
//    //第一个是通过类名方式访问第二个是访问父类作用域下
//    cout << "通过son访问Base的m_a是" << son::Base::m_a << endl;
//}
//
同名静态成员函数
//void test02() {
//    //通过对象
//    cout << "函数通过对象" << endl;
//    son p;
//    p.func();
//    p.Base::func();
//    //通过类名
//    cout << "函数通过类名" << endl;
//    son::func();
//    son::Base::func();
//}
//
//int main () {
//    test01();
//    test02();
//}

//多继承语法(认多个爹)
//class 子类:继承方式 父类1,继承方式 父类2,.。。。。
//大概率出现父类同名成员,加上作用域
//两个父类
//class Base1 {
//    public:
//        int m_a;
//        Base1() {
//            m_a = 100;
//        }
//};
//
//class Base2 {
//    public:
//        int m_a;
//        Base2() {
//            m_a = 200;
//        }
//};
//
子类
//class son: public Base1, public Base2 {
//    public:
//        son() {
//            m_c = 300;
//            m_d = 400;
//        }
//        int m_c;
//        int m_d;
//};
//
//void test01() {
//    son s;
//    sizeof(s);//这里再视频中重新讲了命令提示符
    Base1与2同名成员时,加作用域
//    cout << "Base1里面的m_a是" << s.Base1::m_a << endl;
//    cout << "Base2里面的m_a是" << s.Base2::m_a << endl;
//}
//
//int main () {
//    test01();
//}

//菱形继承,比如羊与驼子都继承动物类,羊驼继承羊和驼子,再分别给
class animal {
    public:
        int m_age;
};//利用虚继承解决菱形问题

//原理是现在不是继承两份数据,而实继承两份指针,通过偏移量找到唯一数据
//animal叫虚基类
class sheep: virtual public animal {
};

class tuo: virtual public animal {
};

class sheeptuo: public sheep, public tuo {
};

int main() {
    sheeptuo st;
    st.sheep::m_age = 18;
    st.tuo::m_age = 28;
    //此时st.m_age会有歧义,直接访问m_age出错,两个父类有歧义加作用域区分
    cout << "st.sheep::m_age是" << st.sheep::m_age << endl;
    cout << "st.tuo::m_age是" << st.tuo::m_age << endl;
    cout << st.m_age << endl; //用虚继承之后解决菱形问题,可以直接访问
    //这份数据有一份就行,菱形继承导致资源浪费有两份
}


 

  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值