• 学习C++的道路 博主会持续更新的


    2018.9.3 今天开始正式上课了  也是好好开始学习C++的日子了 

    今天买了两本书  C++项目开发 与 C接口----等我的书回来一定要好好的学习一波

    博主用的编译软件是VS2017 -----  地址 : https://visualstudio.microsoft.com/zh-hans/vs/whatsnew/

    今天:学习了利用继承改写组合关系 我把今天写的笔记总结了下来  如下(有写的不对的地方,大家不要见怪 提出来我们共同解决):

      1 /*
      2     8:继承使用的两种情况
      3     (1)、类之间有自然的继承关系,一个类另一个类的特例。
      4         fx:一个学生是一个人
      5     (2)、实现代码复用,一个类需要使用另一个类中的成员时
      6     9:继承的好处
      7     (1)、代码复用 code reuse
      8     (2)、使代码容易修改
      9     10:两个类之间的交互关系
     10     (1)、组合类    ------》 一个类中有另一个类的对象 has-a的关系   
     11         ======  组合改继承 那么 我们可以一步一步去拆分进而去得到
     12     (2)、继承      ------》 一个雷是另一个类的特例 is-a的关系
     13 
     14     学到了学到了  输出运算符重载
     15     ostream & operator << (ostream & os, Point & apoint){
     16         os << "Point:X:Y: "<<apoint.x<<","<<apoint.y<<"
    ";
     17         return os;
     18         //其中   Point是具体的某一个类  这个类名是可以进行更改的
     19     }
     20 
     21 */
     22 #include <iostream>
     23 using namespace std;
     24 class Point {
     25 
     26 };
     27 
     28 class Circle {
     29 private:
     30     Point center;
     31     float radius;
     32 };
     33 
     34 class Cylinder {
     35 private:
     36     Circle c;
     37     float height;
     38 };
     39 
     40 //上边是用组合来写的
     41 //接下来给出用继承来写
     42 class Point1{
     43 private:
     44     float x, y;
     45 };
     46 
     47 class Circle1:Point1 {
     48 private:
     49     float radious;
     50 };
     51 
     52 class Cylinder : Circle1 {
     53 private:
     54     float height;  //自己扩展 + 父类的成员 + 爷爷的成员
     55 };
     56 
     57 //接下来书写组合改继承的具体代码  注意:与上边要分开 否则一起运行时会报错的
     58 
     59 #include <iostream>
     60 #include <cmath>
     61 using namespace std;
     62 
     63 class Point {
     64     friend ostream & operator << (ostream & , Point & );
     65 protected:
     66     double x, y;
     67 public:
     68     Point():x(0),y(0){}
     69     Point(double _x, double _y) {
     70         x = _x;
     71         y = _y;
     72     }
     73 };
     74 
     75 ostream & operator << (ostream & os, Point & apoint) {
     76     os << "Point:X:Y " << apoint.x << "." << apoint.y << "
    ";
     77     return os;
     78 }
     79 
     80 //圆继承点
     81 class Circle : public Point{
     82     friend ostream & operator << (ostream &, Circle &);
     83 protected:
     84     double radius;
     85 public:
     86     Circle():Point(),radius(0){}
     87     Circle(double r,double xval,double yval):Point(xval,yval),radius(r){}
     88      
     89     double area() {
     90         return (3.14159 * radius * radius);
     91     }
     92 };
     93 
     94 ostream & operator << (ostream & os, Circle & aCircle) {
     95     os << "Cicle:radius:" << aCircle.radius;
     96     os << aCircle.x << "
    ";
     97     os << aCircle.y << "
    ";
     98     return os;
     99 }
    100 
    101 class Cylinder :public Circle {
    102     friend ostream & operator << (ostream &, Cylinder &);
    103 protected:
    104     double height;
    105 public:
    106     Cylinder() :Circle() { height = 0.0; }
    107     Cylinder(double hv, double rv, double xv, double yv) :Circle(rv, xv, yv) {
    108         height = hv;
    109     }
    110 
    111     double area() {
    112         return (2 * Circle::area() + 2 * 3.14159 * radius * height);
    113     }
    114 };
    115 
    116 ostream & operator << (ostream & os, Cylinder & acylinder) {
    117     os << "cylinder dimensions";
    118     os << "x:" << acylinder.x;
    119     os << " y:" << acylinder.y;
    120     os << " radius: " << acylinder.radius;
    121     os << " height: " << acylinder.height << endl;
    122     return os;
    123 }
    124 
    125 int main(int argc, const char * argv[]) {
    126     Point p(2, 3);
    127     Circle c(7, 6, 5);
    128     Cylinder cyl(10, 11, 12, 13);  //半径不同  调用的函数变量的值不同
    129 
    130     cout << p;
    131     cout << c;
    132     cout << "area circle:" << c.area() << endl;
    133 
    134     cout << cyl;
    135     cout << "area cylinder:" << cyl.area() << endl;
    136 
    137     cout << "area cylinder base is " << cyl.Circle::area() << endl;
    138 
    139     return 0;
    140 }
    继承与组合

    很开心今天书回来了  好好学习

    //今天学习到很过干货

    1、子类的析构函数会自动会调用父类的析构函数

    2、析构函数是存储保存在栈中的  所以在输出析构函数的时候是有一定的顺序的

    3、虚函数----》这是个重点

      (1)、在使用虚函数之后可以不去使用向下转型

      (2)、期望父类指针。不管指向父类还是子类,在调用override函数是,反映真实情况

      (3)、指针或者引用所指向的对象的类型来确定

    4、多态-----个人理解(多种形态) 

        fx: 

          //Base *p = &d1; //其实与多态类似 主类的指针在不断的变化
          //p = &d2; //虚函数的时候只需要改指向就ok
          //p = &b; //指哪一个调用哪一个

    今天的代码:

      1 //虚函数与多态
      2 /*
      3     虚函数的使用(根据父类的引用的指向来选择进行哪一个实现)
      4     虚函数的作用:
      5         (1)、无需向下转型,就可以正确的用父类的指针或引用
      6         (2)、期望父类指针。不管指向父类还是子类,在调用override函数是,反映真实情况
      7         (3)、指针或者引用所指向的对象的类型来确定
      8 */
      9 #include <iostream>
     10 using namespace std;
     11 
     12 class  Base {
     13 public:
     14     virtual void func() {
     15         cout << "Base function" << endl;
     16     }
     17 };
     18 
     19 class Derived1 :public Base {
     20 public:
     21     void func() {
     22         cout << "Derived1 function" << endl;
     23     }
     24 };
     25 
     26 class Derived2 :public Base {
     27 public:
     28     void func() {
     29         cout << "Derived2 function" << endl;
     30     }
     31 };
     32 
     33 void foo(Base & b) {
     34     b.func();
     35 }
     36 
     37 int main() {
     38     //虚函数(一)
     39     /*
     40     Base b;
     41     Derived1 d;
     42     Base *p = &d; //父类指针指向子类对象
     43     Base & br = d; //父类引用指向子类对象
     44     b.func();    //父类版本
     45     d.func(); //子类版本
     46     p->func(); //父类
     47     br.func();
     48     foo(b);
     49     */
     50 
     51 
     52     //虚函数(二)
     53     Base b;
     54     Derived1 d1;
     55     Derived2 d2;
     56 
     57     //Base *p = &d1;   //其实与多态类似   主类的指针在不断的变化  
     58     //p = &d2;   //虚函数的时候只需要改指向就ok
     59     //p = &b;  //指哪一个调用哪一个
     60     //p->func();   
     61 
     62 
     63     Base *p[3] = { &b,&d1,&d2 };  //父类指针数组   -------->   厉害 厉害 学到了  学到了
     64     for (int i = 0; i < 3; ++i)
     65     {
     66         p[i]->func();
     67     }
     68     return 0;
     69 }
     70 
     71 //加强虚函数的使用
     72 #include <iostream>
     73 using namespace std;
     74 
     75 class Thing {
     76 public:
     77     virtual void what_Am_I() {
     78         cout << "I am a Thing.
    ";
     79     }
     80     ~Thing() {
     81         cout << "Thing destructor" << endl;
     82     }
     83 };
     84 
     85 class Animal : public Thing {
     86 public:
     87     virtual void what_Am_I() {
     88         cout << "I am a Animal.
    ";
     89     }
     90 
     91     //子类析构函数会自动调用父类的析构函数
     92     //注意析构函数的存储是保存在栈中的  所以这边输出的时候是有一定的顺序的
     93     ~Animal() {
     94         cout << "Animal destructor" << endl;  
     95     }
     96 };
     97 
     98 int main() {
     99     Thing t;
    100     Animal x;
    101     Thing* array[2]; //声明一个父类指针数组
    102     array[0] = &t;
    103     array[1] = &x;
    104     for (int i = 0; i < 2; i++) {
    105         array[i]->what_Am_I();
    106     }
    107     return 0;
    108 }
    继承与多态

    2018.9.5(上午10点  看了关于本地时间的一些函数)

    http://www.runoob.com/cplusplus/cpp-date-time.html

    一些代码

     1 #include <iostream>
     2 #include <bits/stdc++.h>
     3 #include <ctime>
     4 
     5 using namespace std;
     6 
     7 /*
     8     当地时间的结构体  用于ctime头文件中
     9     struct tm {
    10         int tm_sec;   // 秒,正常范围从 0 到 59,但允许至 61
    11         int tm_min;   // 分,范围从 0 到 59
    12         int tm_hour;  // 小时,范围从 0 到 23
    13         int tm_mday;  // 一月中的第几天,范围从 1 到 31
    14         int tm_mon;   // 月,范围从 0 到 11
    15         int tm_year;  // 自 1900 年起的年数
    16         int tm_wday;  // 一周中的第几天,范围从 0 到 6,从星期日算起
    17         int tm_yday;  // 一年中的第几天,范围从 0 到 365,从 1 月 1 日算起
    18         int tm_isdst; // 夏令时
    19     } 
    20 */
    21 
    22 int main(int argc, char const *argv[])
    23 {
    24     //基于当前系统的当前日期
    25     time_t now = time(0);
    26 
    27     //把 now转换成字符串形式
    28     char* dt = ctime(&now);
    29 
    30     cout<<"本地日期和时间: "<<dt<<endl;
    31 
    32     //把now转换成为tm结构
    33     tm * gmtm = gmtime(&now);
    34     dt = asctime(gmtm);
    35     cout<<"UTC日期和时间: "<<dt<<endl;
    36     
    37     cout<<"1970 到目前经过的秒数:    "<<now<<endl;
    38     
    39     tm * ltm = localtime(&now);
    40     
    41     //输出tm结构的各个组成部分
    42     cout<<"年:    "<<1900 + ltm->tm_year<<endl; 
    43     cout<<""<<1 + ltm->tm_mon<<endl;
    44     cout<<""<<ltm->tm_mday<<endl;
    45     cout<<"时间:    "<<ltm->tm_hour<<endl;
    46     cout<<ltm->tm_min<<":";
    47     cout<<ltm->tm_sec<<endl;
    48     return 0;
    49 }
    ctime

    2018.9.5(下午)

      今天在学习虚函数的基础上,学习了虚析构函数。

      在今天的学习中了解到,如果一个类是父类 那么它的析构函数就必须是虚函数

      如果不是虚析构函数的话就会造成内存泄漏,会引起报错。(在C++学习中一定需要注意)

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class Base {
     5 public:
     6     Base(){}
     7     virtual ~Base() {
     8         cout << "Base destructor!" << endl;
     9     }
    10 };
    11 
    12 class Derived : public Base {
    13 public:
    14     Derived(){}
    15     ~Derived() {
    16         cout << "Derived destructor!" << endl;
    17     }
    18 };
    19 
    20 int main() {
    21     Base p1; //存在于栈区
    22     Base* p2  = new Base(); //存在于堆区
    23     Base *p = new Derived(); //声明一个子类对象在堆空间
    24 
    25     //当把父类的虚构函数变为虚函数是  释放得劲就是子类的成员
    26     delete p; //调用父类的析构函数,子类只释放了继承自父类的成员  内存泄漏
    27     return 0;
    28 }
    虚析构函数

    2018.9.10(前几天有事情,没有更新)

    1、纯虚函数:虚函数只有声明,函数体=0;就是一个纯虚函数
    2、拥有纯虚函数的类叫做抽象类,抽象类只能作为基类,不能实例化对象
    3、抽象类提供不同种类的之类对象的一个接口
    4、纯虚函数被定义在派生类中。如果派生类不重写基类的纯虚函数,则派生类也是一个抽象类

     1 /*
     2     抽象基类与纯虚函数
     3 */
     4 
     5 #include <iostream>
     6 #include <math.h>
     7 using namespace std;
     8 
     9 class Point
    10 {
    11 private:
    12     double x;
    13     double y;
    14 public:
    15     Point(double i, double j) :x(i), y(j) {}
    16 
    17     void print() const
    18     {
    19         cout << "(" << x << "," << y << ")" << endl;
    20     }
    21 };
    22 
    23 class Figure
    24 {
    25 private:
    26     Point center;
    27 public:
    28     Figure(double i = 0, double j = 0) :center(i, j) {}
    29 
    30     Point& location()
    31     {
    32         return center;
    33     }
    34 
    35     void move(Point p)
    36     {
    37         center = p;    //改变图形的中心点
    38         draw();        //调用draw对图形重新绘制
    39     }
    40     //纯虚函数 虚函数只有声明,没有实现,函数体 = 0
    41     virtual void draw() = 0;
    42     virtual void rotate(double) = 0;    // 旋转图形 也没有实现
    43 };
    44     class Circle :public Figure
    45     {
    46     private:
    47         double radius;
    48     public:
    49         Circle(double i = 0, double j = 0, double r = 0):Figure(i,j),radius(r){}
    50         void draw()  //对父类的Figure中的纯虚函数进行实现
    51         {
    52             cout << "A circle with center" << endl;
    53             Figure::location().print();
    54         }
    55     };
    纯虚函数

    2018,.9.11(今天学习了多继承)

    1、第一种

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class A
     5 {
     6 private:
     7     int i;
     8 public:
     9     A(int i):i(i){}
    10     void print()
    11     {
    12         cout << i << endl;
    13     }
    14 };
    15 
    16 class B
    17 {
    18 private:
    19     int j;
    20 public:
    21     B(int j) :j(j) {}
    22     void print()
    23     {
    24         cout << j << endl;
    25     }
    26 };
    27 
    28 class C :public A, B
    29 {
    30 private:
    31     int k;
    32 public:
    33     C(int i,int j,int k):A(i),B(j),k(k){}
    34     void get_Message()
    35     {
    36         A::print();
    37         B::print();
    38     }
    39 };
    40 
    41 int main()
    42 {
    43     C x(5, 8, 10);
    44     x.get_Message();
    45 
    46 
    47     //x.print();   会报错  因为它不知道去调用哪一个父类的print函数
    48 
    49     //针对上一个问题的方法 在子类调用print函数时加上某个父类的作用域函数
    50     x.A::print();
    51     return 0;
    52 }
    多继承

    2、第二种(菱形继承)

     下边代码分两种情况  (1)、一个错误情况  (2)、正确情况

      1 //2、菱形继承(有共同祖先) 二义性  代码解释 
      2 #include <iostream>
      3 using namespace std;
      4 
      5 class R    //祖先类
      6 {
      7 private:
      8     int r;
      9 public:
     10     R(int anInt) { r = anInt; }
     11     void printOn() const { cout << "r=" << r << endl; }
     12 };
     13 
     14 //父类A
     15 class A : public R
     16 {
     17     int a; //父类A会有一份r
     18 public:
     19     A(int int1, int int2) :R(int2) { a = int1; }
     20 };
     21 
     22 //父类B
     23 class B : public R
     24 {
     25     int b;    //父类B会有一份r
     26 public:
     27     B(int int1, int int2) :R(int2) { b = int1; }
     28 };
     29 
     30 //孙子辈的子类继承父类A和B
     31 class C :public A, public B
     32 {
     33     int c; //子类会有两份r,一份来自A,一份来自B
     34 public:
     35     C(int int1, int int2, int int3) :A(int2, int3), B(int2, int3) { c = int1; }
     36 
     37 };
     38 
     39 int main()
     40 {
     41     R rr(10);
     42     A aa(20, 30);
     43     B bb(40, 50);
     44     C cc(5, 7, 9);
     45     rr.printOn();
     46     aa.printOn();
     47     bb.printOn();
     48     cc.printOn(); //error   vs直接报错  不明确
     49     return 0;
     50 }
     51 
     52 /*
     53     为了解决二义性 我们需要使用虚继承
     54     虚继承
     55         1、直接继承祖先的两个基类,在继承是加virtual
     56         2、通过多重继承而来的那个子类,在构造函数时,要调用祖先类的
     57            构造函数。
     58 */
     59 
     60 include <iostream>
     61 using namespace std;
     62 
     63 class R    //祖先类
     64 {
     65 private:
     66     int r;
     67 public:
     68     R(int anInt) { r = anInt; }
     69     void printOn() const { cout << "r=" << r << endl; }
     70 };
     71 
     72 //父类A  虚继承
     73 class A :virtual public R
     74 {
     75     int a; //父类A会有一份r
     76 public:
     77     A(int int1, int int2) :R(int2) { a = int1; }
     78 };
     79 
     80 //父类B  虚继承
     81 class B :virtual public R
     82 {
     83     int b;    //父类B会有一份r
     84 public:
     85     B(int int1, int int2) :R(int2) { b = int1; }
     86 };
     87 
     88 //孙子辈的子类继承父类A和B
     89 class C :public A, public B
     90 {
     91     int c; //子类直接继承祖先类R的成员,再继承两个父类各自扩张的成员
     92 public:
     93     C(int int1, int int2, int int3 ,int int4) :R(int1),A(int2, int1), B(int2, int1) { c = int4; }
     94 
     95 };
     96 
     97 int main()
     98 {
     99     R rr(10);
    100     A aa(20, 30);
    101     B bb(40, 50);
    102     C cc(5, 7, 9,10);
    103     rr.printOn();
    104     aa.printOn();
    105     bb.printOn();
    106     cc.printOn(); 
    107     /*
    108         因为虚继承C中的r和printOn函数直接从R类中继承,所以孙子类中
    109         只会有一份R的成员,不会重复继承
    110     */
    111     return 0;
    112 }
    菱形继承
  • 相关阅读:
    LCA问题第二弹
    LCA问题
    树状数组(Binary Indexed Tree,BIT)
    线段树第二弹(区间更新)
    线段树+RMQ问题第二弹
    RMQ问题第一弹
    分治法二(平面最近点对)
    分治法(一)
    带权并查集
    提交一个变量或数组到另一个jsp页面
  • 原文地址:https://www.cnblogs.com/Yinchen-One/p/9579994.html
Copyright © 2020-2023  润新知