|
TouchGFX是一个基于STM32硬件,由C++写成的软件框架,所以有必要对C++基础有一定的了解 一. C++新特性 5 X; i& h4 a$ D, Q
C语言里,变量初始化必须在程序的前面,而C++则可以随用随定义。C++也可以直接初始化,比如 int x(100),这样就直接赋值 x=100C++的输入输出方式:以cin和cout代替了C语言里的scanf和printf cout语法形式: - cout << x << endl;/ o. s5 Y; f- Y2 J7 l6 x
- // x 可以是任意数据类型(或表达式)
_4 L; P. T a/ j- q3 r - // endl 是换行符,与C里的"\n"效果一样) j! }) |( S# Y/ P
- cout << x << y << endl; //多个变量的输出
复制代码cin 语法形式: - cin >> x; //x可以是任意数据类型
) g$ |9 `3 L. J& X - cin >> x >> y; //多个变量的输入
复制代码C++的命名空间 namespace:using namespace std; - #include <iostream>6 S) V8 k, b/ w" S, B
- using namespace std;
8 y* Q0 u) S0 ~4 A& d - int main(){
2 s3 ?% a/ m# J2 k9 X# K0 f! f+ [) I - cout << "Hello, World!" << endl;4 Y' ^) r! L5 f) @ V' O6 b
- return 0;( d, r; L; I" K2 ^2 D# e
- }
复制代码上面程序中,头文件要写成iostream,因为是标准输入输出流;带".h"的是非标准输入输出流。using是编译指令,声明当前命名空间的关键词,可理解成使用命名空间std,因为cin和cout都是属于std命名空间的,所以使用时须加上using namespace std,也可以写成std::cin和std::cout,其中 :: 表示作用域
( C: H' ]: \ w' e为什么要使用命名空间呢?一些名字易冲突,所以会使用命名空间的方式进行区分,具体来说就是加个前缀。比如C++标准库里面定义了vector容器,自己又写了个vector类,这时名字就冲突了。于是使用标准库里的名字时,都要加上std::的前缀,即std::vector来引用。经常写全名比较繁琐,所以在名字没有冲突的情况下可以添加using namespace std,那么接下去使用标准库里的名字时就可以不用再写std::前缀了 - /***** namespace_example.cpp *****/' B! Y4 N/ n! M. [
- #include <iostream>
9 f( p. M& z" ^ - using namespace std;
) S5 W0 {; m1 }( p" l! o - namespace A { //自定义命名空间A
) X+ z/ u. {7 K4 Y - int x = 1;
3 P! p# P9 F; j. [1 [* I i7 } - void fun() {, r: I3 m' H! j( V
- cout<<"A namespace"<<endl;5 r# s' e0 r& |; G9 E
- }
" Y& K5 @# n/ [. s% s - }
- F0 O. x( N9 b( p - using namespace A; //声明使用命名空间A* `3 j. \2 x* ~0 o, u0 h) U6 R X
- int main(){
2 P7 U/ t# F% J% F3 c4 s/ T - fun(); //声明使用命名空间A后,可直接使用fun()
$ ?* ^* k+ w$ H/ i/ ^ - A::x = 3; //将A命名空间下的x重新赋值为3
. b4 u6 B, _7 L7 }! W2 D. k - cout<<A::x<<endl;
0 h: I$ M; D( S - A::fun();5 F; b' h, [6 v8 W$ B4 j
- return 0;& a4 a2 D1 n6 l7 f! C
- }
复制代码执行下面的指令开始编译 - g++ namespace_example.cpp -o namespace_example
复制代码执行./namespace_example后结果如下 - A namespace
3 b& k# E- D/ m8 c# s - 36 U' W* _' P# R6 N- l
- Anamespace
复制代码二. C++面向对象
0 l% b5 y; T) W7 d4 B: o# ~8 l
面向对象的三大特征是继承,多态和封装 2.1 类和对象 类是C++的核心特性,通常被称为用户定义的类型。类用于指定对象的形式,包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员,函数在一个类中被称为类的成员。从类中实例化对象分两种方法,一种是从栈中实例化对象,一种是从堆中实例化对象
; e1 Z i- F5 w6 `3 q- /***** class_dog_example.cpp *****/
2 D' \6 v6 j, |) U( ?5 F - #include <iostream>
7 x9 ]* \& ~$ _ - #include <string>
/ n# q$ k/ W0 ~+ D3 d, X) D4 g - using namespace std;
8 D8 w3 Z- p2 L! k' Y7 p+ \- E
+ H: [ J5 m* Q ?) B \1 S$ \3 r+ [7 @: f- class Dog { //定义一个类
! C; J9 X$ j& T6 Z: x$ Y+ f% i - public: //访问限定符public(公有的),不写的话默认是private
# N. r! }% k u - string name;0 P$ R: C @; R+ p! z- s3 m9 i
- int age;# K9 g; E0 L' ?$ C7 D: A
-
. u5 r% ?0 m$ [6 o* G' [ - void run() { //定义一个方法
! T5 @% h4 X* r' w6 @" J - cout<<"小狗的名字是:"<<name<<","<<"年龄是"<<age<<endl;$ i6 @! m5 ]4 T4 ^" x6 C1 E
- } @7 _9 M# u, y) j
- };
( I! b# x( `4 O- Q
7 t5 r# H9 T3 b+ g9 ^! U+ B( j- int main() {
X6 l0 }0 ~' k" O - /* 从栈中实例化一个对象dog1 */
5 g9 ]; {% {9 M6 F/ l - Dog dog1;
9 b# e2 a4 Z5 b* @6 d, z - dog1.name = "旺财"; //为dog1的成员变量赋值
3 O8 ~/ @+ c# d0 j$ n( ?3 \ - dog1.age = 2; //为dog1的成员变量赋值6 g* L6 C- {7 ` _
- dog1.run(); //调用run()方法,打印dog1的相关变量信息
# E3 [1 G, H' s1 E8 _6 I - /* 从堆中实例化对象,使用关键字new的都是从堆中实例化对象 */8 T5 _, |8 _7 w1 E
- Dog *dog2 = new Dog(); * q: I/ H) s+ B1 E
- if (NULL == dog2) { //从堆中实例化对象需要开辟内存,指针会指向那个内存; X. I2 ]3 [+ z' g( B0 @, D) i
- return 0;
" h. L8 U8 r2 k# W' m e# B2 G, L9 ` - }3 ^% Q8 W; [2 {4 N7 v( s( R c
- dog2->name = "富贵"; //为dog2的成员变量赋值
4 y! Y& N! w2 N4 H+ S7 P - dog2->age = 1; //为dog2的成员变量赋值
4 j9 N/ ~3 u* m/ L) X' V- ]% I7 E - dog2->run(); //调用run()方法,打印dog2的相关变量信息
! ^/ Z% J. x2 ^( i: Y - ' a/ t q; e L# C( F
- delete dog2; //释放内存6 Z) A( q; p' ~. c K1 K
- dog2 = NULL; //将dog2重新指向NULL/ d) Q5 [1 y V5 E" X
- return 0;/ G7 B3 G6 n) K; s, e
- }" @0 h! V) s/ |
- 执行下面的指令开始编译
3 |$ g: D7 [3 W" a3 ?$ P, u - . h) Q: V. K+ }$ W' Q; E
- g++ class_dog_example.cpp -o class_dog_example2 Z' s# E7 |3 o
- 执行./class_dog_example后结果如下
" |7 v# H$ E; D2 Y3 z4 F' i - 4 T, ]3 N8 ?- C6 J
- 小狗的名字是:旺财,年龄是2
+ g, k$ V7 D) Y0 K - 小狗的名字是:富贵,年龄是1
- E1 }& ~+ ?# A4 I. J - ⏩ 构造函数与析构函数
$ {. g9 A# J& b2 j - 构造函数在对象实例化时被系统自动调用,仅且调用一次。构造函数的特点如下:
+ L! C/ }; ^3 x0 D - 构造函数必须与类名同名
/ V+ @9 e- t) |4 S - . W! p8 _! A6 S6 b. ^% |
- 可以重载,没有返回类型
6 P- v7 ?& ~8 c' p" u! V, K' [3 C
8 i# _0 W) H( U) q! I" u- 构函数在对象结束其生命周期时系统自动执行。析构函数的特点如下:2 D1 I0 Y8 L2 v0 Y3 f" C
- 析构函数的格式为~类名(),调用时释放内存(资源)5 {/ n8 [6 ?' G( ^& D, s
4 h* m% T# j, c9 i8 W- ~类名()不能加参数,没有返回值 h/ l' p; `, h- Y
- & L; A/ c* k# @% o/ D. W& k
- 定义类时, 如果没有定义构造函数和析构函数, 编译器就会生成一个构造函数和析构函数, 只是这个构造和析构函数什么事情也不做。当要使用构造函数和析构函数时就需要自己在类里添加
; Y) s% [- X+ Z - : W2 F8 f, m, d$ u% [+ ?. V5 D4 B
- /***** structor_example.cpp *****/2 B4 z6 R+ \- M9 J
- #include <iostream>
) L% }8 ]& ]8 ~& X - #include <string>: @) j. _- f3 t7 _0 T# R
- using namespace std;! _9 }1 }9 E' D( l
$ ~! `$ ^- R/ [; ^$ ^' c! T- class Dog { //定义一个类,并在里面写了构造函数和析构函数9 R! c( r# m o- k
- public:
4 X8 J* n& e8 o0 B. ` - Dog();
+ @3 x, _0 V* M! R6 c% V. ` - ~Dog();* z B- u# ?7 W7 `- H6 t: u
- };! Y+ q, @+ D8 Q/ x5 Q# Y
- 6 v4 J# [. g2 u7 {
- int main() {. ^+ f8 {9 y: S& _1 k E
- Dog dog; //实例化一个dog对象* {7 {; [- E7 G. J! G
- cout<<"构造与析构函数示例"<<endl;
4 Y# _& G U& h4 S" I$ `$ Z' T0 \ - return 0;
3 h) k" [' a& z: g - }; X+ V1 w# E3 g* g+ i' P: _
- //类的函数可在类里实现,也可在类外实现,在类外实现时需要使用“::”' \* ~3 c3 P- \. w" J+ K- w4 w
- Dog::Dog() {# a( [( z# J2 `' r7 d
- cout<<"构造函数执行! "<<endl;# n- | k# T; q! g! N
- }
~1 L- I# ?4 }9 ] m4 D
0 y5 I) @8 [# x! G, ~- Dog::~Dog() {! p1 }, p) K6 I4 o. i# }' |2 E
- cout<<"析构函数执行! "<<endl;, a# o, h# X7 M% y
- }
复制代码执行下面的指令开始编译 - g++ structor_example.cpp -o structor_example+ F g6 x) i2 @7 V! I7 U
复制代码执行./structor_example后结果如下 - 构造函数执行!
' N3 r1 D% Z' Q/ g6 g& [3 t - 构造与析构函数示例
+ |# S* u2 Y O/ W. j1 w - 析构函数执行!
复制代码this指针 每个对象都拥有一个this指针,this指针记录对象的内存地址。this指针是指向类自身数据的指针,简单来说就是指向当前类的当前实例对象。关于类的this指针有以下特点: ) g9 X, ^/ }; J) W2 O0 T6 Q
this只能在成员函数中使用,全局函数、静态函数都不能使用this this在成员函数的开始前构造,在成员函数的结束后清除 this指针会因编译器不同而有不同的放置位置。可能是栈,寄存器或者全局变量 ' l1 q+ h0 ?' \7 c* a
- /***** this_pointer_example.cpp *****/
7 o8 l+ }3 ~" u - #include <iostream>0 {6 ^7 Q3 j8 e" |8 Q' l
- #include <string>
?! T* s7 P* U2 D* E# U0 B% m - using namespace std;
$ P& s7 |0 ], ^ - . y% R( f) E/ t. W1 C4 x1 N
- class Dog {% m/ n5 w$ T3 \# W3 t, ~5 m
- public:+ c8 D6 n6 X$ X- a
- string name;
# w8 y' s& W3 ]8 C - void func();
. y7 q. v9 \2 y) H! J, g3 g( _2 i% M - };7 Y7 g$ a0 _' I1 o) W
- 0 A) w" J( _+ n c* l7 A! ]
- int main() {
# a8 }1 A+ b; L% d7 ?3 y - Dog dog;
9 e/ u4 }3 A5 q: I8 l# d" o - dog.func();
) U+ `6 n! S+ e/ q9 C - return 0;
, \+ V: b- T0 G. P* X7 `* b - }
* X5 A3 ~" |5 p8 ]: V - //在类的成员函数里使用了this指针, 并指向了类里的成员name; A$ c7 _5 Q3 _+ y0 J2 h
- void Dog::func() {1 a4 `! K% B2 Y+ [# d6 ~
- this->name = "旺财";
+ f- T; J! }5 F( {- ]' k9 q6 d - cout<<"小狗的名字叫: "<<this->name<<endl;
: i0 S6 N- |5 p% W; c& R8 G - }
复制代码执行下面的指令开始编译 - g++ this_pointer_example.cpp -o this_pointer_example
复制代码执行./this_pointer_example后结果如下 - 小狗的名字叫:旺财$ F: x d% G+ Z# ]1 h% Z
复制代码
' P% R6 S" o, t3 F3 p/ M2 \, Q 转载自嵌入式攻城狮 0 K2 S; h; \0 x" b$ m# n
6 b# U; A, n$ J1 E z
|