学习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<<"\n";
 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 << "\n";
 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 << "\n";
 97     os << aCircle.y << "\n";
 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.\n";
 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.\n";
 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 }
菱形继承

 

posted @ 2018-09-03 18:20  奋斗の小白  阅读(340)  评论(0编辑  收藏  举报