你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

C++之类与对象的实现

[复制链接]
gaosmile 发布时间:2020-6-3 21:45
1、来聊聊(轻松一刻)

0 x% y* E3 P4 d" B: l- c; W( i
     随着年龄的增长,我们会觉得属于自己的时间和空间会渐渐变少,一部分留给家人一部分留给公司,自己的兴趣和爱好也渐渐的成为了一些非常奢侈的东西,最近一些地方鼓励2.5天的休息时间,先不说我们是否能够享受到,但至少看到了这种思想的涌现,大家开始对自己的生活质量有了更高的要求!
! R( ^1 W, C4 w$ K3 d
    好了,今天我们继续重温C++的第二篇内容,从第一讲的阅读量来看大家可能对C++的内容有些抗拒,一些小伙伴反馈C++内容太多了,水有点深不敢碰,有些的觉得学好C就可以等等等,不过作者这里的讲述都是为后面的内容进行铺垫的,所以大家如果有兴趣还是补充一些该部分的基础。
% w5 `& U9 ?& O8 A9 P
2、类的实现
    类的第一个重要属性是封装性,我们使用类只需要熟悉类的对外接口,而并不需要熟悉类的具体实现,除非你想实现一个新的类,就相当于我们平时调用函数只需要知道函数的输入和输出,并不需要知道具体的内部实现,除非你写一个新的函数。9 D3 b8 s7 f) `! q# e5 l
1)教你写C++第一类
7 X, ^; u( [/ y3 b5 B- V
    在C++中我们定义类都是使用class关键字,类似于C语言的struct,下面我简单的写了一份参考代码供大家学习:/ w0 y% ~/ D; s% w! n; |0 U
1//FileName:Add.h
7 W4 y5 H: W# k% I7 d0 } 2#ifndef _ADD_H_& A1 p1 I+ t* T
3#define _ADD_H_5 j8 \1 W" z9 \
4# G+ ?7 o5 o' g+ L: U% c
5//类的定义:定义了一个加法类
: O5 l  F* c3 H6 J# `9 T 6class Add. C& @& V" [/ C7 n1 E+ y0 x! Q
7{
! y3 X+ p/ N; `  E" m% H" w! E 8//私有成员区域定义:只能内部访问   n. A3 e0 f% @& u: {( j
9private:& u# U6 B  R3 l$ h/ w$ q
10    int Sum;) j- X. M8 g% ]3 ^: E2 d
11- ?: v+ M# R4 F" K
12//保护成员定义区域:后面再说明
* v6 p7 _: l& x6 p' i13protected: & ?. r9 p( B, \5 n' s& ~
14
( x# A& P+ R) \% c( F( T% S( {9 w15//公有成员区域定义:对外接口
( m) v3 x. z+ I. R$ |0 S- b- u16public:+ I7 R3 S/ d0 M+ Q/ q/ ]( N$ [
17    void Cal(int a, int b);1 ]( S: H1 ?0 s" {
18    int GetResult(void);
  C3 y" O8 l! r$ h, `8 ^19};- p% t% T0 D$ _: y
20
  O: s9 R* N, D5 X& Y- O21#endif
9 L& z7 A$ m0 ~  i9 p: h6 f5 y
) j1 U  N5 U" d
1//FileName:Add.cpp
* A. U! y4 V: B! ~9 ^3 A 2#include "Add.h"
4 i- B5 Q2 U8 U1 b 3/***********************************************
1 }! Q1 j1 J( m- a 4 * Fuction : 这里是类的公有接口函数Cal的实现
1 _9 c( O% k; s/ I+ h/ p, k 5 * Author  : (公众号:最后一个bug)
- F" }* [. B3 Z+ t( s; M6 Q2 M 6 **********************************************/

  `/ j+ O" r; p7 I# p4 Z 7void Add::Cal(int a,int b)
# ?8 o/ s7 Y& k: v$ B 8{
8 q7 ~0 u7 X: U$ r 9    Sum = a + b;. H2 B4 Y1 s, W) V0 Y, l. l$ R/ s
10}: }+ x, D' S- B
11/**************************************************
1 I" _+ L+ B5 s! g: B8 K3 a4 R12 * Fuction : 这里是类的公有接口函数GetResult的实现 ' y& T7 i1 v5 M6 _! `+ N
13 * Author  : (公众号:最后一个bug)0 y* F9 ?# `% ~2 R. U, ^$ J
14 *************************************************/

  x; \/ J6 n( t5 y15int Add::GetResult(void)
; U; Y' x2 Y% `* N4 ~$ ?* X% y16{
- b' S8 `+ x  @% ]/ n7 u5 C* c- c3 U17    return Sum;
6 M) g, d4 s* I, c& l  a18}
& L7 I$ ?! ~+ ~: m2 {

) b: S( t# x  G& N
1//FileName:main.cpp 1 K! O& H& }8 R! V& v/ W  p
2#include <iostream>' g; n9 x/ G1 ^* \/ U
3#include "Add.h"
1 c3 _; h7 s$ ^. E& K 4using namespace std;" [, J/ o% R, m; [
5: u/ E* a8 |; f( C6 A
6int main(int argc, char** argv) {
2 A7 k) E) d5 q7 c* n, e 7: c$ y, ?5 [) N, W/ r
8    //1、通过类Add定义一个对象add
% j; Y. P& i! T8 r 9    Add add;
# e( f* r8 G2 I2 T8 r& p0 f) K0 p10    //2、通过对象调用类的公共接口进行访问
: x  s2 C/ c2 B4 p- X; S11    add.Cal(3,5);
4 A! S* b" J) e% S, C6 e( C. Y( \. X12    //3、输出最后的接口 2 F! }( H3 l) R; J" |: P
13    cout << "result :"<< add.GetResult()<<endl;
0 [& Y6 B$ i0 U% h. p5 p14    cout << "公众号:最后一个bug!"<<endl;  o9 g7 P# w( S7 n
15    return 0;
6 k7 B$ m. x* L6 K4 x8 K16}

1 l: W% K: E' u& s, M2 \1 d
       解析一下 : 作者在这里对类通过一个.cpp和.h文件进行封装,这个与C语言中的模块化设计是类似的,以后复杂类的实现也大体是这样一个书写方式。我们先不纠结那些在C中没有看到过的用法,然后把class换成struct,这样的代码应该大家都能够看明白吧,唯一区别比较大的是在class中C++为每个成员(包括变量和方法)设置了一定的访问权限(private-私有/protected-保护/public-公有)。
4 ~% `. o/ `) W! C+ \8 V
2)类构造与析构 5 W4 y' F) [+ h/ F
    大家在学习C++的时候一定会觉得这两个名词有点变扭,其实也不难理解,把我们创建的对象比作一张手机电话卡,我们在初次使用的时候主要进行身份登记、并为你分配一个手机号码,办理手机套餐等等,类似的C++会为你开放一个函数接口供你来初始化,这就是构造函数;同样我们现在不想使用这张电话卡了就需要到对应的地方对手机号码进行注销,如果你还欠费的话还要补缴话费等等,类似的在C++中也会为你开放一个对应的函数接口供你来进行最后的处理,这就是析构函数。
& T* X+ g- z6 ?( A
    好了,这里我在上面的基础上加上析构和构造函数,大家看一看:5 r) t! @. o+ N5 b7 u
1//FileName:Add.h
( l3 N' C3 k7 E3 D 2#ifndef _ADD_H_3 r/ k+ E1 S2 W) U
3#define _ADD_H_3 E2 q9 N% I4 b
4
6 w, o, C. @0 h  L6 c, E- N& ` 5//类的定义:定义了一个加法类 6 s6 N/ r9 l6 I- U0 H
6class Add
4 u, H2 a7 W" A  t3 m7 t 7{
" ~2 G6 A1 _3 B* f/ g 8//私有成员区域定义:只能内部访问 9 R6 i* f2 J, J4 t
9private:3 _% R1 g& _) K$ a, o2 i9 P
10    int Sum;7 |% H" _! T% H/ O7 H( Z2 ]0 x
11
/ C# L/ v) A' s' i7 @% e12//保护成员定义区域:后面再说明
/ D9 i+ a1 {+ [4 g5 `13protected: 1 @" g; X' b* B5 h. F3 D
14; O, i+ ^. P9 s
15//公有成员区域定义:对外接口 8 x  J/ W9 N4 [% C
16public:1 u4 H: k% a8 N* z8 o5 c
17    Add();    //构造函数 / P* }1 r" v5 M9 e# y, T1 e0 n
18    ~Add();   //析构函数
3 P! C, P) o2 ?9 ]& m19    void Cal(int a, int b);6 e# X6 v" P5 {9 L2 W# U  f- ]- m" t
20    int GetResult(void);8 Y8 x% \  D" u% f; X0 Q. v
21};. E6 w* w6 e1 D3 r  J  [
22#endif
) o2 d# y  a3 V! {' W
0 O% k1 \) p0 T
1/***********************************************) a+ D6 B+ Z1 J9 P
2 * Fuction : 类Add的构造函数
9 w) \2 q8 k5 o3 a 3 * Author  : (公众号:最后一个bug)* M8 ~# v' y* \# f
4 **********************************************/
: c! Z  p" Z0 p- s- M  q& L
5Add::Add()
. T( i2 N- q/ w7 l4 Z* `2 } 6{
0 I9 i, t; y( G/ q) D0 G 7    //进行对应的资源初始化工作
# Q; Y$ c2 z4 ?- L; \) ]7 w6 N  Y 8    cout<<"调用构造函数: Add()"<<endl;
; ~, b/ w6 v, o# W0 }" b/ V 9}& n& \" V$ E1 I8 Z/ {1 b# K' d% ^
104 N7 R) T2 k# j3 m8 [
11/***********************************************
* G' O6 U; ~2 K% s- ^12 * Fuction : 类Add的析构函数 ; [4 k! {& ^& a; W; }
13 * Author  : (公众号:最后一个bug)
6 S; L1 a# ^! k5 D$ D; c: b- E$ {3 E14 **********************************************/
& f! Z3 n7 P+ ]2 g
15Add::~Add()
; |- t3 q) N: g" x/ Z: G16{7 J  e2 ^# P# a5 e
17    //进行对应的资源释放工作   B5 Z$ Q& v$ s5 G
18    cout<<"调用析构函数: ~Add()"<<endl;4 n9 M! _& }' u. |$ y' J( v/ }% A
19}
, p/ y2 i; o0 ]4 ~# p
    输出的结果如下:
# ^: d$ Y/ D  m2 d
微信图片_20200603214341.png
       解析一下 : 一个类的构造函数和析构函数实现的基本形式如上面的代码所示,其函数名称和类名是完全一致的,对于构造函数是可以含有参数的,不过没有返回值类型声明,析构函数两者都没有;他们都可以分别在对象创建和销毁的时候自动调用;对于构造函数内容稍微多一点,他和普通函数一样也支持重载,还有初始化列表的使用等等,大家可以具体查阅资料学习一下,以后的文章也会具体提到。
0 ^4 k* v. s$ \  k* m4 O
    注意一点 : 我们类中可以包含其他类实例化对象,实例化类的时候也会调用对应的构造和析构函数,那么调用的顺序和栈有点类似,先调用成员的构造,然后调用自身构造,调用析构函数正好与构造函数调用顺序相反。
$ p6 v1 a. V- y3 B( |. e. P
3)类也可以有自己的成员 % s7 _/ [4 e/ Z8 X$ o
    通过上面的学习我们知道,类实例化的每个对象都会拥有各自的成员和方法,也就是说对象的成员都属于对象,每个对象使用类中定义的成员和方法是相互独立的,而我们的类是否拥有自己的成员呢?答案肯定是有的--静态成员。
9 R- u- C( C& Y* V6 t  c6 W' ]
    类的静态成员分为成员变量和成员函数,我们回头想想C语言,C语言中函数里面定义静态变量,其分配的内存空间是单独的,而非栈中,那么C++的静态变量也是类似的,其具有独立的内存,其属于类,而不再属于具体的对象,用static修饰即可。
/ C+ Q9 l& i6 O  _7 d" f, n
    下面继续修改了上面的小程序:7 W- @! f) f2 v% N4 `8 }# e$ z* [
1//FileName:main.cpp 8 T% v; N" Z# z/ R7 G' f5 i! Z
2#include <iostream>& N% v8 |" V: _
3#include "Add.h"% b% M3 @4 l" T3 ?, m  f7 |) W# m
4using namespace std;0 i  o9 Y0 C2 a7 {, _- _2 h
57 T, u+ O: k+ R8 w0 N
6int main(int argc, char** argv) {* H7 \* o4 h' X' F; ]0 u) q: H$ H
75 v6 k& n* ?4 g: Q+ U) e/ v
8    //1、通过类Add定义一个对象add
* d! L  {0 V+ D% @9 B 9    Add add1;' Y& E8 Y5 b/ a& @& U- k
10    Add add2;& T; f# C7 X: P/ z! V9 w/ b
11    //2、通过对象调用类的公共接口进行访问 / G2 r% j  h% ^) G, X
12    add1.Cal(3,5);
8 b" z5 R* B; Z# t3 H5 o4 y13    add2.Cal(3,5);
% D" M  C$ g0 I4 S$ Q# ~& I8 [7 N14    //3、输出最后的接口 ! g( h4 c% L  M# I, F3 h
15    cout << "result :"<< add1.GetResult()<<endl;: e: b  N: J$ ]. P2 ?1 A
16    cout << "公众号:最后一个bug!"<<endl;
' w2 T$ D' ~7 d9 L  P2 C17    return 0;
1 Y% Z) L. x1 t( P8 P, p18}
! U& C& b4 D" U2 w
) y+ B+ g4 \% ~
1//FileName:Add.h
. R# i, o% t, [) R4 q9 e( ` 2#ifndef _ADD_H_3 P3 M( x0 v% N7 r5 Z8 _
3#define _ADD_H_
4 f7 [: R$ Y  z! T- G 4
# O6 ^: u& G8 C1 v; n, V, P" I 5//类的定义:定义了一个加法类 ' ^0 w) d% x' G% g0 i$ J( Y
6class Add
! g; f4 c/ d) `' c+ Z6 m& V 7{
! P' ^/ w9 r# V6 w3 J" v) E3 `; N5 z! Y 8//私有成员区域定义:只能内部访问
- w5 k" c6 P0 ?8 D) u* e* ] 9private:" V$ _, K/ B) P5 }
10    int Sum;
) ]# K+ f8 f: H, O11% L' n+ }  V* i6 w
12//保护成员定义区域:后面再说明
* S+ B7 o1 {- p3 a4 a13protected:
. I* b% M/ ~& U8 \147 e3 w$ b5 \7 M! W
15//公有成员区域定义:对外接口
; c5 g7 B( e9 o" C; C' t16public:
# Q0 U6 \* a. V$ ^0 L17    Add();    //构造函数 9 {' t; Z- m- }% `/ {7 o  g
18    ~Add();   //析构函数
7 ]' q+ k- L5 S8 X$ q* Y4 s19    void Cal(int a, int b);
7 @$ L' U2 v7 Z4 H# ~20    int GetResult(void);, ^7 ^  L/ @2 N8 B6 y& p  I
21    static int count;  //定义一个类的静态变量
; r2 w/ W1 X/ ~% [22};2 R! v5 L3 S. i: @! a5 m
23#endif
! N; O1 m0 l8 K. N
! v$ E* P( w4 @9 U
1//对于静态变量需要单独初始化 - `. F+ v1 x0 C+ M  @; f
2int Add::count = 0;
+ j$ W2 X- ^2 s4 k& T 3/***********************************************
8 R& a! j  T2 I+ r' p4 y 4 * Fuction : 类Add的构造函数 ; M$ m% E+ A' U/ p8 A
5 * Author  : (公众号:最后一个bug)7 R! L4 X6 e$ F
6 **********************************************/
" d- T# }( [: H, J6 P
7Add::Add()
4 l5 N7 U9 N- ~, d 8{
' d6 Y5 j% W" Q! v! H0 {  { 9    count++;
& I8 ]6 f% {3 t4 t7 d% J10    cout<<"count = "<< count <<endl;0 W6 [9 e0 ]' y7 g
11  V+ f# }2 t* Y4 |9 ]4 L) S* k
12    //进行对应的资源初始化工作
  `! K6 y# x! W: L$ V13    cout<<"调用构造函数: Add()"<<endl;
, [, [& ^/ d- f5 d2 k14}: D7 R) Q8 u; G6 ~6 I6 Q
15
/ A7 l& ?7 Q9 j* l" Z, W* O9 c16/***********************************************% z/ Q" ^* L7 t- u/ h; u7 L8 |
17 * Fuction : 类Add的析构函数
& J" i  g2 G; q+ N/ J- i18 * Author  : (公众号:最后一个bug)) y. g, b3 A' `% y* x( g! O0 v
19 **********************************************/

( `( Z" }4 q3 ]$ X20Add::~Add(). p2 Q& E) q0 r0 F: `' u
21{8 f; W, [  C4 U6 h* A& T& }, ^
22    count--;4 a. W7 h7 q$ Q7 N$ [
23    cout<<"count = "<< count <<endl;
; n# Y! K+ c: g6 Q& `24* s7 n. U# E' t3 m3 d5 x2 L
25    //进行对应的资源释放工作
0 {- `( ^/ f& p) I26    cout<<"调用析构函数: ~Add()"<<endl;
& T( a$ u. _# Z9 i27}
/ q) H) ?! r% v) o
       最后的结果:0 N& [) y8 ~8 t7 J9 }( K1 S$ g  y5 [  U
微信图片_20200603214345.png
    解析一下:对于静态变量由于不属于对象,所以需要额外再进行初始化,同时上面的结果也表示count是同一块内存区域,对于public型静态变量我们可以通过类名直接访问,同样定义的static函数,也可以通过类名直接调用,属于类而不属于对象。
9 g* i" G) o- j6 L8 s- j
3、最后小结
    对于重温C++系列大家如果感兴趣的一定要看看详细的教材等,作者这里不可能全部讲解清楚,仅仅只是为了向大家更加形象的展示一些C++常规操作,为以后一些软件设计思想和系统项目分析进行铺垫。

$ R0 Z. R/ F* p. ~- Z
赞 收藏 评论2 发布时间:2020-6-3 21:45

举报

2个回答
李康1202 回答时间:2020-6-4 08:53:19
谢谢分享
heiyewuyue 回答时间:2020-6-5 09:56:42
谢谢分享
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版