zoukankan      html  css  js  c++  java
  • c++学习

    类与对象

    重载

    赋值运算符重载

     1 #include <iostream>
     2 using namespace std;
     3 
     4 //赋值运算符重载
     5 
     6 class Person
     7 {
     8 public:
     9 
    10     int *m_Age;
    11 
    12     Person(int age)
    13     {
    14         m_Age = new int(age);
    15     }
    16 
    17     ~Person()
    18     {
    19         if(m_Age != NULL)
    20         {
    21             delete m_Age;
    22             m_Age = NULL;
    23         }
    24     }
    25 
    26     //重载赋值运算符
    27     Person& operator=(Person &p)
    28     {
    29         //编译器提供浅拷贝
    30 
    31         //判断是否有属性在堆区,如果有,就先释放干净再深拷贝
    32         if(m_Age != NULL)
    33         {
    34             delete m_Age;
    35             m_Age = NULL;
    36         }
    37 
    38         //深拷贝
    39         m_Age = new int(*p.m_Age);
    40 
    41         //返回对象自身
    42         return *this;
    43     }
    44 
    45 };
    46 
    47 
    48 void test01()
    49 {
    50     Person p1(18);
    51     cout << "年龄:" << *p1.m_Age << endl;
    52 
    53     Person p2(20);
    54 
    55     //赋值操作,相当于浅拷贝,会触发double free的操作
    56     p2 = p1;
    57 
    58     cout << "年龄:" << *p2.m_Age << endl;
    59 
    60 }
    61 
    62 int main()
    63 {
    64     test01();
    65 }
    View Code

    关系运算符重载

     1 #include <iostream>
     2 #include <string>
     3 using namespace std;
     4 
     5 //重载关系运算符
     6 
     7 class Person
     8 {
     9 public:
    10     Person(string name,int age)
    11     {
    12         m_Name = name;
    13         m_Age = age;
    14     }
    15     
    16     //重载 == 号
    17     bool operator==(Person &p)
    18     {
    19         if(this -> m_Name == p.m_Name and this -> m_Age == p.m_Age)
    20         {
    21             return true;
    22         }
    23         else
    24             return false;
    25     }
    26 
    27 
    28 public:
    29     string m_Name;
    30     int m_Age;
    31 };
    32 
    33 
    34 void test01()
    35 {
    36     Person p1("tom",18);
    37     Person p2("tom",18);
    38 
    39     if(p1 == p2)
    40         cout << "p1和p2相等" << endl;
    41     else
    42         cout << "p1和p2不相等" << endl;
    43 }
    44 
    45 int main()
    46 {
    47     test01();
    48 }
    View Code

    函数调用运算符重载

    • 函数调用运算符()也可以重载
    • 称为仿函数:在类中重载了小括号
    • 调用非常灵活
     1 #include <iostream>
     2 #include <string>
     3 using namespace std;
     4 
     5 //重载函数调用运算符
     6 
     7 class myAdd
     8 {
     9 public:
    10 
    11     //函数调用运算符重载
    12     int operator()(int a,int b)
    13     {
    14         return a+b;
    15     }
    16 };
    17 
    18 int myadd(int a,int b)
    19 {
    20     return a+b;
    21 }
    22 
    23 void test01()
    24 {
    25     myAdd add1;
    26     int ret = add1(1,2);
    27     cout << "仿函数返回:" << ret << endl;
    28     int ret1 = myadd(1,2);
    29     cout << "真实函数返回:" << ret1 << endl;
    30 }    
    31 
    32 int main()
    33 {
    34     test01();
    35 }
    View Code

    继承

    继承是面向对象三大特性之一

    作用:可减少重复代码

    继承基本语法

    在一个网页中许多信息都是重复的,比如顶部信息,底部信息和侧边栏,所以我们可用继承的方式来写

     1 #include <iostream>
     2 #include <string>
     3 using namespace std;
     4 
     5 //继承好处:减少重复代码
     6 //语法 class 子类: 继承方式 父类
     7 // 子类 == 派生类
     8 // 父类 == 基类
     9 
    10 class PageBase
    11 {
    12 public:
    13     void top_page()
    14     {
    15         cout << "网页的顶部信息" << endl;
    16     }
    17     void bottom_page()
    18     {
    19         cout << "网页的底部信息" << endl;
    20     }
    21     void left_page()
    22     {
    23         cout << "网页的侧边栏信息" << endl;
    24     }
    25 };
    26 
    27 class Main_Page : public PageBase
    28 {
    29 public:
    30     void content()
    31     {
    32         cout << "主页面中独有的信息" << endl;
    33     }
    34 };
    35 
    36 class Second_Page : public PageBase
    37 {
    38 public:
    39     void content()
    40     {
    41         cout << "第二页中独有的信息" << endl;
    42     }
    43 };
    44 
    45 
    46 int main()
    47 {
    48     Main_Page p1;
    49     p1.top_page();
    50     p1.bottom_page();
    51     p1.left_page();
    52     p1.content();
    53 
    54     Second_Page p2;
    55     p2.top_page();
    56     p2.bottom_page();
    57     p2.left_page();
    58     p2.content();
    59 }
    View Code

    继承方式

    继承方式一共有三种

    • 公共继承:父类中的啥属性到子类中不变,比如public还是public,protect还是protect
    • 保护继承:父类中的所有权限到子类都变成了保护权限
    • 私有继承:父类中的所有权限到子类都变成了私有权限

    无论哪种继承方式都无法访问父类中的private的东西

     1 #include <iostream>
     2 #include <string>
     3 using namespace std;
     4 
     5 class Base
     6 {
     7 public:
     8     int m_A;
     9 protected:
    10     int m_B;
    11 private:
    12     int m_C;
    13 };
    14 
    15 class Son1:public Base
    16 {
    17 public:
    18 
    19     void func()
    20     {
    21         m_A = 10;
    22         m_B = 10;
    23         //m_C = 10;
    24     }
    25 
    26 };
    27 
    28 class Son2:protected Base
    29 {
    30 public:
    31 
    32     void func()
    33     {
    34         m_A = 10;
    35         m_B = 10;
    36         //m_C = 10;
    37     }
    38     // 在该类中所有的属性都是protected属性
    39 };
    40 
    41 class Son3:private Base
    42 {
    43 public:
    44 
    45     void func()
    46     {
    47         m_A = 10;
    48         m_B = 10;
    49         //m_C = 10;
    50     }
    51     // 在该类中所有的属性都是private属性
    52 };
    53 
    54 
    55 int main()
    56 {
    57     Son1 s_public;
    58     s_public.m_A = 10;
    59     //s_public.m_B = 10;
    60 
    61     Son2 s_protected;
    62     //s_protected.m_A = 10;
    63 }
    View Code

    继承中的对象模型

    问题:从父类继承过来的成员,哪些属于子类对象中?

     1 #include <iostream>
     2 using namespace std;
     3 
     4 // 继承中的对象模型
     5 
     6 class Base
     7 {
     8 public:
     9     int m_A;
    10 protected:
    11     int m_B;
    12 private:
    13     int m_C;
    14 };
    15 
    16 class Son:public Base
    17 {
    18 public:
    19     int m_D;
    20 };
    21 
    22 void test()
    23 {
    24 
    25     // 16:在父类中非静态成员属性都会被子类继承下去
    26     // 虽然私有属性无法访问,但是也被继承了
    27     cout << "size of Son:" << sizeof(Son) << endl;
    28 }
    29 
    30 int main()
    31 {
    32     test();
    33 }
    View Code

    继承中构造和析构顺序

    子类继承父类后,当创建子类对象,也会调用父类的构造函数

    问题:父类和子类的构造函数谁先谁后?

     1 #include <iostream>
     2 using namespace std;
     3 
     4 // 继承中的构造函数,和析构函数 顺序
     5 
     6 class Base
     7 {
     8 public:
     9     Base()
    10     {
    11         cout << "Base的构造函数" << endl;
    12     }
    13     ~Base()
    14     {
    15         cout << "Base的析构函数" << endl;
    16     }
    17 };
    18 
    19 class Son:public Base
    20 {
    21 public:
    22     Son()
    23     {
    24         cout << "Son的构造函数" << endl;
    25     }
    26     ~Son()
    27     {
    28         cout << "Son的析构函数" << endl;
    29     }
    30 };
    31 
    32 void test()
    33 {
    34     Son s1;
    35 }
    36 
    37 int main()
    38 {
    39     test();
    40 }
    View Code

    继承同名成员处理方式

     1 #include <iostream>
     2 using namespace std;
     3 
     4 // 继承中的构造函数,和析构函数 顺序
     5 
     6 class Base
     7 {
     8 public:
     9     Base()
    10     {
    11         m_A = 100;
    12     }
    13     void func()
    14     {
    15         cout << "Base中的func调用" << endl;
    16     }
    17     
    18 public:
    19     int m_A;
    20 };
    21 
    22 class Son:public Base
    23 {
    24 public:
    25     Son()
    26     {
    27         m_A = 200;
    28     }
    29     void func()
    30     {
    31         cout << "Son中的func调用" << endl;
    32     }
    33 public:
    34     int m_A;
    35 };
    36 
    37 //同名属性处理方式
    38 void test1()
    39 {
    40     Son s1;
    41     // 如果出现同名成员,默认调用子类的成员,如果要调用父类,则要加作用域
    42     cout << "m_A = " << s1.m_A << endl ;
    43     cout << "m_A = " << s1.Base::m_A << endl;
    44 }
    45 
    46 // 同名函数处理方式
    47 void test2()
    48 {
    49     Son s2;
    50     s2.func();
    51     // 如果子类中出现和父类中同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数(包括重载的)
    52     // 如果想访问父类的成员函数,则必须加作用域
    53     s2.Base::func();
    54 }
    55 
    56 int main()
    57 {
    58     test1();
    59     test2();
    60 }
    View Code

    总结

    1. 子类对象可以直接访问到子类中同名成员
    2. 子类对象加作用域可以访问到父类对象的同名成员
    3. 如果子类中出现和父类中同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数(包括重载的)

    继承同名静态成员处理方式

    同非静态的成员处理方法一样

     1 #include <iostream>
     2 using namespace std;
     3 
     4 
     5 
     6 class Base
     7 {
     8 public:
     9     static int m_A;
    10     static void func()
    11     {
    12         cout << "Base static func" << endl;
    13     }
    14 };
    15 
    16 int Base::m_A = 100; // 定义静态成员属性在类外必须初始化,且所有对象共享这个静态成员属性
    17 
    18 
    19 class Son:public Base
    20 {
    21 public:
    22     static int m_A;
    23     static void func()
    24     {
    25         cout << "Son static func" << endl;
    26     }
    27 };
    28 
    29 int Son::m_A = 200;
    30 
    31 //同名静态属性
    32 void test1()
    33 {
    34     Son s1;
    35     cout << "通过对象访问:" << endl;
    36     cout << "Son下静态成员属性" << s1.m_A << endl;
    37     cout << "Base下静态成员属性" << s1.Base::m_A << endl;
    38 
    39     cout << "通过类名访问:" << endl;
    40     cout << "Son下静态成员属性" << Son::m_A << endl;
    41     // 第一个双冒号:代表通过类名访问,第二个双冒号:代表访问父类作用域下
    42     cout << "Base下静态成员属性" << Son::Base::m_A << endl;
    43 }
    44 
    45 
    46 //同名静态函数
    47 void test2()
    48 {
    49     Son s1;
    50     s1.func();
    51     s1.Base::func();
    52 
    53     Son::func();
    54     Son::Base::func();
    55 }
    56 
    57 int main()
    58 {
    59     //test1();
    60     test2();
    61 
    62 }
    View Code

    多继承语法

    c++允许一个类继承多个类

    语法:class 子类:继承方式 父类1,继承方式 父类2……

    菱形继承

    概念:

    两个派生类继承同一个基类

    又有某个类同时继承这两个派生类

    菱形继承问题:

    1,两个派生类继承了基类的数据,当派生类的子类使用数据时,会引发二义性

    2,子类的子类继承基类,继承了两份数据,其实只需要一份就可以了

    多态

    多态的基本概念与语法

    多态是c++面向对象三大特性之一

    多态分类

    • 静态多态:函数重载和运算符重载属于静态多态,复用函数名
    • 动态多态:派生类和虚函数实现运行时多态

    区别:静态多态编译阶段就确定函数地址,动态多态运行时才确定

     1 #include <iostream>
     2 #include <string.h>
     3 using namespace std;
     4 
     5 class Animal
     6 {
     7 public:
     8     void speak()
     9     {
    10         cout << "动物在说话" << endl;
    11     }
    12 };
    13 
    14 class Cat : public Animal
    15 {
    16 public:
    17     void speak()
    18     {
    19         cout << "小猫在说话" << endl;
    20     }
    21 };
    22 
    23 void doSpeak(Animal &animal)    // Animal &animal = cat;
    24 {
    25 
    26     animal.speak();
    27     // 运行结果是动物在说话  原因:地址早绑定,无论传什么动物都是动物在说话
    28     // 要想猫在说话,就需要地址晚绑定
    29 }
    30 
    31 void test01()
    32 {
    33     Cat cat;
    34     doSpeak(cat);
    35 }
    36 
    37 int main()
    38 {
    39     test01();
    40 }
    View Code
     1 #include <iostream>
     2 #include <string.h>
     3 using namespace std;
     4 
     5 class Animal
     6 {
     7 public:
     8     virtual void speak()    // 虚函数,地址晚绑定
     9     {
    10         cout << "动物在说话" << endl;
    11     }
    12 };
    13 
    14 class Cat : public Animal
    15 {
    16 public:
    17     // 重写概念:函数返回值类型,函数名,形参列表完全相同
    18     // 子类中的virtual可写可不写
    19     void speak()
    20     {
    21         cout << "小猫在说话" << endl;
    22     }
    23 };
    24 
    25 // 动态多态满足条件:
    26 // 1,有继承关系
    27 // 2,子类重写父类的虚函数
    28 
    29 // 多态使用方法:父类的指针或者引用,指向子类对象
    30 
    31 void doSpeak(Animal &animal)    // Animal &animal = cat;
    32 {
    33 
    34     animal.speak();
    35 }
    36 
    37 void test01()
    38 {
    39     Cat cat;
    40     doSpeak(cat);
    41 }
    42 
    43 int main()
    44 {
    45     test01();
    46 }
    View Code
  • 相关阅读:
    从零开始学SQLSERVER-UNION
    从零开始学SQLSERVER-BETWEEN
    从零开始学SQLSERVER-LIKE
    从零开始学SQLSERVER-存储过程(基础用法)
    从零开始学SQLSERVER-TOP
    从零开始学SQLSERER-INNER JOIN
    从零开始学SQLSERVER-DELECT(删除)
    从零开始学SQLSERVER-ORDER BY(排序)
    从零开始学SQLSERVER-WHERE
    使用 C# 9 的records作为强类型ID
  • 原文地址:https://www.cnblogs.com/lemon629/p/13806210.html
Copyright © 2011-2022 走看看