|
TouchGFX是一个基于STM32硬件,由C++写成的软件框架,所以有必要对C++基础有一定的了解 一. C++新特性
% E& u ]# N# b5 Y3 u2 d* V- i. o
C语言里,变量初始化必须在程序的前面,而C++则可以随用随定义。C++也可以直接初始化,比如 int x(100),这样就直接赋值 x=100C++的输入输出方式:以cin和cout代替了C语言里的scanf和printf cout语法形式: - cout << x << endl;
! n( G! K! T/ w& U8 d G - // x 可以是任意数据类型(或表达式)
+ {. c$ a: c0 z* {* r/ M3 R - // endl 是换行符,与C里的"\n"效果一样5 \! j# K/ O& C1 `5 d1 N
- cout << x << y << endl; //多个变量的输出
复制代码cin 语法形式: - cin >> x; //x可以是任意数据类型- l; [% ?. c c( T
- cin >> x >> y; //多个变量的输入
复制代码C++的命名空间 namespace:using namespace std; - #include <iostream>
, {3 i7 v" p, @) R - using namespace std;3 v- D% X Z. R; W8 f9 t
- int main(){
7 h9 b2 P, v' w# x. b; } - cout << "Hello, World!" << endl;
# @# K' F& X% {! q" w# n0 ] - return 0;; W; [' [ r1 a$ A1 T$ `
- }
复制代码上面程序中,头文件要写成iostream,因为是标准输入输出流;带".h"的是非标准输入输出流。using是编译指令,声明当前命名空间的关键词,可理解成使用命名空间std,因为cin和cout都是属于std命名空间的,所以使用时须加上using namespace std,也可以写成std::cin和std::cout,其中 :: 表示作用域
9 h8 g* V" x/ M* b# B: T为什么要使用命名空间呢?一些名字易冲突,所以会使用命名空间的方式进行区分,具体来说就是加个前缀。比如C++标准库里面定义了vector容器,自己又写了个vector类,这时名字就冲突了。于是使用标准库里的名字时,都要加上std::的前缀,即std::vector来引用。经常写全名比较繁琐,所以在名字没有冲突的情况下可以添加using namespace std,那么接下去使用标准库里的名字时就可以不用再写std::前缀了 - /***** namespace_example.cpp *****/
( S, Z1 j+ z% m, |& V/ @ - #include <iostream>
0 z9 v5 _1 S6 @9 ^; [* z4 b0 @ - using namespace std;
9 ?5 ?* s* v, t: p - namespace A { //自定义命名空间A
9 o5 G0 {) L0 j3 \- u6 ~ - int x = 1;3 V& B% f2 N+ i0 d6 Y& }/ e
- void fun() {$ C$ S6 e2 b1 B
- cout<<"A namespace"<<endl;) m* x+ l6 q/ N- U
- }
6 B6 f) c% e; q2 [4 I/ W8 A* l - }
) C* Y5 n. f4 Q) S2 k# T; x - using namespace A; //声明使用命名空间A
6 U/ x* H. y% G - int main(){6 } L8 W( r9 X; ?: F
- fun(); //声明使用命名空间A后,可直接使用fun()
4 {7 P' L# m) f. ^# M1 y - A::x = 3; //将A命名空间下的x重新赋值为36 g* v: o4 M- W# d4 z
- cout<<A::x<<endl;
4 |+ m; k3 L6 u5 m8 H - A::fun();
/ |5 M. p: U& s; M5 [. Q9 l - return 0;7 ?8 r7 N/ \# t2 e$ w6 {4 J. \, N
- }
复制代码执行下面的指令开始编译 - g++ namespace_example.cpp -o namespace_example
复制代码执行./namespace_example后结果如下 - A namespace
1 O: _& A: M6 e7 Y6 t1 V - 36 L7 h# B; x( f$ E% a, ~
- Anamespace
复制代码二. C++面向对象
~; C( w% W) X4 ]' o/ P
面向对象的三大特征是继承,多态和封装 2.1 类和对象 类是C++的核心特性,通常被称为用户定义的类型。类用于指定对象的形式,包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员,函数在一个类中被称为类的成员。从类中实例化对象分两种方法,一种是从栈中实例化对象,一种是从堆中实例化对象
6 H: i% j, T, M+ k" y- /***** class_dog_example.cpp *****/
k3 }# d: @: M2 N r$ i1 G - #include <iostream>
s- Y, \' J* u6 } - #include <string>
, H6 R* G2 ?, {$ u. A! v4 J - using namespace std;
: j0 j: ? x& s- M. @
y) N% A" r1 {( m" I6 A- class Dog { //定义一个类
7 Q/ s% T. |% w$ v9 p - public: //访问限定符public(公有的),不写的话默认是private
4 i4 A1 z, }9 k- O7 v - string name;
" T0 R) X; Z3 B - int age;
9 S1 l' y1 c. g7 t( p( V -
# V0 K) y2 R4 f+ Z - void run() { //定义一个方法/ H5 A5 l' U& R, }' o
- cout<<"小狗的名字是:"<<name<<","<<"年龄是"<<age<<endl;. l5 {+ L$ d- e' C! u. y
- }
$ ]. N: a. q- M5 x8 u# R* X' r - };8 a! [5 ~, k7 X4 u$ t; X5 P
" k# j8 [8 {2 w1 ]2 D6 u9 V1 k- int main() {
% _) G; U8 E4 Q: F - /* 从栈中实例化一个对象dog1 */
" f; p D* [' M; z - Dog dog1;
0 q c5 m7 J0 f2 K! s - dog1.name = "旺财"; //为dog1的成员变量赋值
, B/ x3 T5 X$ V+ _. @: j; s! j/ g9 P - dog1.age = 2; //为dog1的成员变量赋值
D) P/ k! e2 _0 o - dog1.run(); //调用run()方法,打印dog1的相关变量信息
2 ]- N; j+ U7 {0 [. C: H - /* 从堆中实例化对象,使用关键字new的都是从堆中实例化对象 */
- K" v. V7 O' _- R - Dog *dog2 = new Dog(); # K g5 G) }' S" s
- if (NULL == dog2) { //从堆中实例化对象需要开辟内存,指针会指向那个内存- W" v9 R3 U1 i, c" q9 O+ Q
- return 0;% Y. f, L; ]! y) Y7 E
- }4 ^$ ^9 B% D% D6 Q; {
- dog2->name = "富贵"; //为dog2的成员变量赋值" c% Z" y. R9 i' [, ~4 N; U
- dog2->age = 1; //为dog2的成员变量赋值
( ]7 ^8 K' F* r( h7 B+ O3 @, d: y - dog2->run(); //调用run()方法,打印dog2的相关变量信息
5 P- ~* C. q/ P0 h/ F5 C( K2 t
$ Q& b i, G1 w0 k$ s- delete dog2; //释放内存; ]# n7 m+ |7 [1 O
- dog2 = NULL; //将dog2重新指向NULL
; Q7 ]' i1 D/ e( F' Y: J - return 0;
7 b; ?$ O! |) y& ` o8 U8 Z - }; S5 ~! }$ \1 G$ a! P
- 执行下面的指令开始编译( H: _: r/ c' f6 O% `. D
- " M( z/ }6 [! Z1 T+ Q
- g++ class_dog_example.cpp -o class_dog_example# _+ y C$ g6 T- N% ]
- 执行./class_dog_example后结果如下3 ]0 W5 E; O b) `4 W' E# k
- % G) H: V y- p, w
- 小狗的名字是:旺财,年龄是2! X& g) ]* M5 ~/ ~. A W) i
- 小狗的名字是:富贵,年龄是1
' ~( |( T2 m" _2 }& F - ⏩ 构造函数与析构函数
; w7 P. T9 }# H4 Y" P( z# v - 构造函数在对象实例化时被系统自动调用,仅且调用一次。构造函数的特点如下:
1 t* \3 G; s1 n/ @; @* r6 f - 构造函数必须与类名同名
" b5 r& g- V$ B
8 \( h# p* P3 g- 可以重载,没有返回类型
0 p6 E2 s% b8 z( `( c% N2 _
/ x0 I( \; c, L2 V8 b6 G- 构函数在对象结束其生命周期时系统自动执行。析构函数的特点如下:9 u# o1 N0 Q4 Y* J+ J
- 析构函数的格式为~类名(),调用时释放内存(资源)
' N% k% K5 q& T$ w - 2 G+ N! | T+ W8 |7 ~
- ~类名()不能加参数,没有返回值7 x% Q1 Y+ m. `4 p/ r' R
- ; R1 r( v) k c2 j$ V5 R
- 定义类时, 如果没有定义构造函数和析构函数, 编译器就会生成一个构造函数和析构函数, 只是这个构造和析构函数什么事情也不做。当要使用构造函数和析构函数时就需要自己在类里添加' t1 F' i& z: E; a. x
- % C& \4 n/ [. ?5 C% N1 h
- /***** structor_example.cpp *****/$ w; V: N- S2 J; D
- #include <iostream>
: n( S2 R+ o9 g8 i: i9 \4 |. J - #include <string>' x& s* }* J* v7 I; d
- using namespace std;
; E& v/ ]# k; g5 m: l - . v1 T& B5 ]- p ]' \/ e8 s
- class Dog { //定义一个类,并在里面写了构造函数和析构函数" _5 Q- u* A5 _5 ?$ a# X
- public:
- Q& N# o& Z5 S - Dog();
! v% |9 {) i7 L( m8 Z! c - ~Dog();
* D! Q2 C' m8 |( S, }0 H5 Y - };
6 k4 J, f% c4 m3 T - ( Q3 h1 a7 Q( t/ v. l b
- int main() {
8 N; D. _! K5 E- } - Dog dog; //实例化一个dog对象- d6 ]8 r* V+ |3 Z, W( S
- cout<<"构造与析构函数示例"<<endl;+ j7 q1 V4 g0 I
- return 0;
" a; a3 f6 P V0 X6 @- m - }
* \7 i9 b& n- K+ w# n" ^ - //类的函数可在类里实现,也可在类外实现,在类外实现时需要使用“::”
7 D: Y5 s$ F( q' O2 B2 e - Dog::Dog() {
# X( y0 q- H8 X. n! ]3 j2 |, J - cout<<"构造函数执行! "<<endl;4 L$ {, a( c; z6 \; U
- }
3 @3 g5 b# P& v - : P! U& d5 m) d+ ~
- Dog::~Dog() {. @; I/ G0 I6 \& Q" A( A5 c
- cout<<"析构函数执行! "<<endl;6 t2 Q' ?2 s, U% b
- }
复制代码执行下面的指令开始编译 - g++ structor_example.cpp -o structor_example2 F* o& r9 W. b
复制代码执行./structor_example后结果如下 - 构造函数执行!
- [7 m" m7 {+ T J6 B. g - 构造与析构函数示例/ n8 f: u$ J& l n4 ~$ s0 N! _0 o
- 析构函数执行!
复制代码this指针 每个对象都拥有一个this指针,this指针记录对象的内存地址。this指针是指向类自身数据的指针,简单来说就是指向当前类的当前实例对象。关于类的this指针有以下特点:
1 P) d( ~0 \2 f6 [# p6 ithis只能在成员函数中使用,全局函数、静态函数都不能使用this this在成员函数的开始前构造,在成员函数的结束后清除 this指针会因编译器不同而有不同的放置位置。可能是栈,寄存器或者全局变量 " M- `( [, z7 N, E# g
- /***** this_pointer_example.cpp *****/
* K( w% P% j* ] - #include <iostream>& q: z7 E0 z/ ~: G# C1 E4 x+ f
- #include <string>
3 T$ F4 X- y/ ~/ `/ [6 \2 n - using namespace std;" b. t) s( F7 n$ f3 K k3 `/ @: \
8 t, r: |- @- V' {/ ?- class Dog {
# O+ d+ Y* {/ s8 M9 u0 g - public:
- d% r! \; ^% B' p u$ s2 ? - string name;6 X. y0 u, R+ l3 P! f( Z. ^4 V
- void func();- ?5 U( a! d1 i
- };, q0 w2 ]7 f2 B& v1 @
" z2 e8 x* N; y& n: E( Y7 `" B- int main() {
' R& ~ q0 p$ l2 }2 C - Dog dog;, ]3 y, s7 Q/ L/ _1 E
- dog.func();
/ C/ |. M& f! D; J5 t: | - return 0;; j! X3 c! h! _9 Y9 q- P: e; H
- }
; Y4 [0 E" t4 C& m" S% k - //在类的成员函数里使用了this指针, 并指向了类里的成员name
5 L$ f, y4 I1 d6 v4 ?# k h& s9 V - void Dog::func() {
' e; `3 p) O$ B7 G$ i0 w2 U) } - this->name = "旺财";
- x+ K; a+ | D% a - cout<<"小狗的名字叫: "<<this->name<<endl;, H1 Z( j9 x( N) ~& x9 v. J
- }
复制代码执行下面的指令开始编译 - g++ this_pointer_example.cpp -o this_pointer_example
复制代码执行./this_pointer_example后结果如下 - 小狗的名字叫:旺财
% d# z" x: K4 T
复制代码
. |; o& S8 Y; A8 } 转载自嵌入式攻城狮 , j3 q- D# I( D& ?6 N' C
( w2 f4 b2 C2 [1 z1 y+ z) o
|