|
TouchGFX是一个基于STM32硬件,由C++写成的软件框架,所以有必要对C++基础有一定的了解 一. C++新特性 4 Z7 M ?! N4 z: D' j6 j# d! U5 [
C语言里,变量初始化必须在程序的前面,而C++则可以随用随定义。C++也可以直接初始化,比如 int x(100),这样就直接赋值 x=100C++的输入输出方式:以cin和cout代替了C语言里的scanf和printf cout语法形式: - cout << x << endl;6 M: ~/ \, g# M' s; D
- // x 可以是任意数据类型(或表达式)
* y( M: ^; g3 Z - // endl 是换行符,与C里的"\n"效果一样3 b# P2 R a, T1 F& |/ Z7 D
- cout << x << y << endl; //多个变量的输出
复制代码cin 语法形式: - cin >> x; //x可以是任意数据类型
& p a% } @. P+ v - cin >> x >> y; //多个变量的输入
复制代码C++的命名空间 namespace:using namespace std; - #include <iostream>
0 ~- j3 B; K) o - using namespace std;
# P8 s& ?! O! X. b. C - int main(){
7 @( `7 a7 B/ C2 |5 C+ o$ F - cout << "Hello, World!" << endl;3 W. a1 H" t2 E0 j" M9 t0 @, ]
- return 0;
5 v' O" x; g2 C/ F3 v - }
复制代码上面程序中,头文件要写成iostream,因为是标准输入输出流;带".h"的是非标准输入输出流。using是编译指令,声明当前命名空间的关键词,可理解成使用命名空间std,因为cin和cout都是属于std命名空间的,所以使用时须加上using namespace std,也可以写成std::cin和std::cout,其中 :: 表示作用域 6 x0 i/ ?. h+ ?- U! C+ j
为什么要使用命名空间呢?一些名字易冲突,所以会使用命名空间的方式进行区分,具体来说就是加个前缀。比如C++标准库里面定义了vector容器,自己又写了个vector类,这时名字就冲突了。于是使用标准库里的名字时,都要加上std::的前缀,即std::vector来引用。经常写全名比较繁琐,所以在名字没有冲突的情况下可以添加using namespace std,那么接下去使用标准库里的名字时就可以不用再写std::前缀了 - /***** namespace_example.cpp *****/
2 t# u+ [6 Y; X# ` - #include <iostream>4 S8 o6 c# S9 y' `1 @
- using namespace std;
" Z& z6 r) N; w7 l6 K8 O0 ]) J6 [) n - namespace A { //自定义命名空间A
! c+ a. ?. ]! R$ ]: H - int x = 1;
2 a- G. W; y i. g0 v" g( B - void fun() {& E' l& [ ?9 E3 V3 b, ]4 V
- cout<<"A namespace"<<endl;, [; f& g/ f8 ]6 I. @
- }; p' B+ K! I j6 P8 q3 P/ Q! r5 D t
- }
c) T; E3 U# N- P: I0 G - using namespace A; //声明使用命名空间A! g/ c8 D% F% ^0 \3 O! X! X6 c* y3 Z* P
- int main(){
8 B! e+ U2 x/ n# X' F - fun(); //声明使用命名空间A后,可直接使用fun()+ g! y* i9 F$ I
- A::x = 3; //将A命名空间下的x重新赋值为3
: p5 U" b6 Z5 d& I, Q# d - cout<<A::x<<endl;) h* K: z) v4 y2 h
- A::fun();' K2 X" } l. c! E
- return 0;
4 d* V4 j( h8 l: o - }
复制代码执行下面的指令开始编译 - g++ namespace_example.cpp -o namespace_example
复制代码执行./namespace_example后结果如下 - A namespace
- f) R( |2 o0 H; I+ L/ ? - 3
7 O# R. z$ Q+ r) [! s7 ~0 Q/ o$ e - Anamespace
复制代码二. C++面向对象
: [9 E6 a$ O$ H) z) K
面向对象的三大特征是继承,多态和封装 2.1 类和对象 类是C++的核心特性,通常被称为用户定义的类型。类用于指定对象的形式,包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员,函数在一个类中被称为类的成员。从类中实例化对象分两种方法,一种是从栈中实例化对象,一种是从堆中实例化对象 3 r! w1 K" l2 q6 b) ~
- /***** class_dog_example.cpp *****/
, z, o+ r; W ^0 \2 L- q7 | T - #include <iostream>
9 A& S, {% F! q# e - #include <string>
' Z& m! |. D- r: f/ D8 _ - using namespace std;/ ^0 b% ~# J: H. g- p1 Q3 O
- $ N8 d; ?+ }$ M) J7 |
- class Dog { //定义一个类) I6 V" U& C. x# }4 f% k0 |! R
- public: //访问限定符public(公有的),不写的话默认是private, C& f% v4 [* j4 ]5 M C
- string name;
0 s/ Y8 m& ?, h# y+ ^- Z - int age;' h- U5 B0 a+ r' \2 W; `' I
-
* Z! ?* I+ \" C' _5 H7 ^, m6 P3 |0 V - void run() { //定义一个方法8 H& \4 M# E! A* d
- cout<<"小狗的名字是:"<<name<<","<<"年龄是"<<age<<endl;
7 l0 Q! K0 `$ g! \* B4 ^ - }7 {9 C w. y! C+ R& j; \4 h
- };
# y/ c. R2 ~2 p: r* d% y) ]7 O
4 p+ Q7 L; ~) I0 E6 B* ~/ W$ Z- int main() {
; q" l( T# \6 H' g3 ~# p2 L - /* 从栈中实例化一个对象dog1 */ l: y' I/ N) F* ], H
- Dog dog1; 5 k& N' B. x9 s; Y& }! C: x
- dog1.name = "旺财"; //为dog1的成员变量赋值
! t( Z7 |0 d& ?% c* Z# Q, k1 S. y& s - dog1.age = 2; //为dog1的成员变量赋值5 _( g2 j6 ]7 d/ _5 O# s r4 c
- dog1.run(); //调用run()方法,打印dog1的相关变量信息4 _" @" i8 A- N u1 y' |
- /* 从堆中实例化对象,使用关键字new的都是从堆中实例化对象 */0 Z( Y* v! z) v% L& h6 @ p
- Dog *dog2 = new Dog();
( h" H# {4 k3 \, K/ i - if (NULL == dog2) { //从堆中实例化对象需要开辟内存,指针会指向那个内存! o+ j7 I0 P" M! C
- return 0;4 T8 b- R- k$ v8 s. V. c9 _. F
- }
6 F" K+ g# U. _& _: k7 V3 T - dog2->name = "富贵"; //为dog2的成员变量赋值% _; x4 {8 x- a( ?7 L! e8 S+ U
- dog2->age = 1; //为dog2的成员变量赋值% y9 m5 o# S: h* y, ^
- dog2->run(); //调用run()方法,打印dog2的相关变量信息, S% q& T0 I' w+ V: E4 J
9 r7 J6 V$ J) s" Y2 S- delete dog2; //释放内存
1 w" U2 _9 [6 A- ]' D, }! P - dog2 = NULL; //将dog2重新指向NULL X4 u9 s8 q+ r& _ M
- return 0;9 |7 e b( T7 I# n# D
- }
; N4 ]4 D: q- J4 | - 执行下面的指令开始编译
. r- U- {& ~( j9 X, n
, S L' Y1 O) _7 `* a- g++ class_dog_example.cpp -o class_dog_example7 J9 k0 N9 O2 r* J1 Y
- 执行./class_dog_example后结果如下
: A$ y4 l3 w2 E0 w; h - / s. o+ ? P. \2 M
- 小狗的名字是:旺财,年龄是2
1 s# ~6 D* @3 t" U - 小狗的名字是:富贵,年龄是1
5 O# V8 I( o# y/ Y: j. l# D - ⏩ 构造函数与析构函数5 L/ k! I) s7 t& ` [$ Y% f& q
- 构造函数在对象实例化时被系统自动调用,仅且调用一次。构造函数的特点如下:
& |% {" R2 @# g, ?) u9 F - 构造函数必须与类名同名: N {: L) r% o" ?' i; d6 S' q
- " _8 U& Q- T" l$ L- X* s3 E
- 可以重载,没有返回类型3 h: A4 y8 w3 o D7 n6 b
( w( K- K, g ~- ]) j& y- 构函数在对象结束其生命周期时系统自动执行。析构函数的特点如下:% U" ]0 W; ^$ h6 x( m
- 析构函数的格式为~类名(),调用时释放内存(资源)" j4 v* A5 r" t2 Y4 E2 D
- ) F$ \) }2 t3 P
- ~类名()不能加参数,没有返回值
/ T+ q: [- d0 q+ s$ M J$ S4 w - % `* Z4 z$ ]9 S# F, v1 X
- 定义类时, 如果没有定义构造函数和析构函数, 编译器就会生成一个构造函数和析构函数, 只是这个构造和析构函数什么事情也不做。当要使用构造函数和析构函数时就需要自己在类里添加
% m4 `, J4 c$ {+ S; N* M- e
6 a" n- t: } B7 V7 O1 Y- /***** structor_example.cpp *****/6 O# `0 l2 H% U' }: {
- #include <iostream>
7 h5 n* [' I7 J4 H% e$ Q - #include <string>, o) _, R! y: I- @2 ^
- using namespace std;. G6 Y; o- t7 y; {
- * C, n1 |+ q% m/ W% ?
- class Dog { //定义一个类,并在里面写了构造函数和析构函数7 ]$ i& ~" n$ t( R; r# v
- public:
2 \5 P1 @' F" t5 n4 L- g0 }& K - Dog();
0 [! u' e% n; N1 ~$ G3 |! P; a - ~Dog();
, S) A7 S' `$ A3 \7 x/ c# e: J' f - };
( H9 f, q+ ~+ U, z5 ~1 _ - 7 ~2 a }, M" F8 x1 W0 ~$ n) T
- int main() {
0 A; w9 Z2 e% \# q* \8 U - Dog dog; //实例化一个dog对象
- D i6 @4 o6 M1 G - cout<<"构造与析构函数示例"<<endl;
! r7 u9 V8 y1 @, k- {2 ]' @ - return 0;
k1 o7 j, {% t+ C) {. U. t" { - }
/ ~* B* T, @ X1 V; z - //类的函数可在类里实现,也可在类外实现,在类外实现时需要使用“::”
$ f0 ]- F' l8 O+ |) \: C- \) F - Dog::Dog() {
- z; |% k2 r+ j3 q, p - cout<<"构造函数执行! "<<endl;6 ~1 Y. D- B& k2 c
- }- g# k/ K' C2 x1 ^" \# D4 x* l
- 9 V* i' x5 L* w" e% G! M
- Dog::~Dog() {: P" q; U7 x8 f/ p1 @
- cout<<"析构函数执行! "<<endl;
]$ C: z6 z; ?" K: m8 J1 D) l - }
复制代码执行下面的指令开始编译 - g++ structor_example.cpp -o structor_example
o( x: F+ U" ]& z
复制代码执行./structor_example后结果如下 - 构造函数执行!
' _* n, b! r' O+ q& \ - 构造与析构函数示例
P' w, T5 G/ V - 析构函数执行!
复制代码this指针 每个对象都拥有一个this指针,this指针记录对象的内存地址。this指针是指向类自身数据的指针,简单来说就是指向当前类的当前实例对象。关于类的this指针有以下特点: * h) h i& ~9 E1 K$ @+ v
this只能在成员函数中使用,全局函数、静态函数都不能使用this this在成员函数的开始前构造,在成员函数的结束后清除 this指针会因编译器不同而有不同的放置位置。可能是栈,寄存器或者全局变量
4 S% s& F2 u) ~0 @- D( z. p# P0 G$ U
- /***** this_pointer_example.cpp *****/6 w O( @7 P# D' }7 c' m' }6 }
- #include <iostream>$ j' r8 D- b& l+ y) U: ]2 ~, w
- #include <string>' z5 h* ^: Q. \' p( i
- using namespace std;
! M* n V! ^ K- `
2 B" \' o! Y! y9 K* L# S- class Dog {
( W( ]: d9 z; k" N* b; d# C( d4 V - public:0 M# @% J: b# b
- string name;1 q3 ~) Q( S7 ~
- void func();7 P1 s# l/ t1 Q
- };
: _% B/ ~% c, n' W. q
3 f7 h; \1 e, Z4 b$ N- int main() {
/ I( V7 S7 t0 e D5 Y - Dog dog;
}/ Z. c2 J( G% b - dog.func();
7 y2 l! e7 k- E, L Y3 |3 u' ] - return 0;
/ ^4 U8 T) f1 O6 D8 ^6 l7 {8 O - }
0 A+ }- a: j) P% s- F% o - //在类的成员函数里使用了this指针, 并指向了类里的成员name3 n5 b- B, D+ g6 w
- void Dog::func() { V; z$ t: q5 E- B1 M/ H! K
- this->name = "旺财";& }+ o2 k+ f* S8 H) E, B7 u# d
- cout<<"小狗的名字叫: "<<this->name<<endl;' t l4 S9 I' z7 P7 Z
- }
复制代码执行下面的指令开始编译 - g++ this_pointer_example.cpp -o this_pointer_example
复制代码执行./this_pointer_example后结果如下 - 小狗的名字叫:旺财' m' D/ x! d0 V) S M5 P# Q
复制代码 4 z% o1 f$ x: A M# P. R7 K
转载自嵌入式攻城狮
# y9 C7 ?) I3 [; |2 Y
' O8 x" I" ~6 Z/ b% | |