C++程序语言设计 Chapter 3: The C in C++
OutLine of the chapter Same thing in program language Make and Ant
诸子百家——名家 名家是战国时期的重要学派之一,因从事论辩名(名称、概念)实(事实、实在)为主要学术活动而被后人称为名家。 http://www.guoxue.com/gxrm/gx_mingj.htm 公孙龙(约公元前325—前250年),赵国人。生平事迹不详。他是名家代表人物之一,有14篇著作留世,但在唐时已散失了一大半,如今可能只《公孙龙子》一书。名家最著名的命题,是公孙龙的"白马非马"论。
“白马非马”论 庄子评:“能胜人之口,不能服人之心。” 城门上告示:“马匹不得入城”。公孙龙同志骑白马而来,遭拒入。公孙龙一脸正色:“告示上写的是‘马’,而我骑的是‘白马’,难道 ‘马’等于 ‘白马’吗?”。守门士兵觉得白马还真不是马,于是放行。 如果白马是马,黑马也是马,那么岂不白马等于黑马,所以,不能说白马是马。“白马非马”是中国哲学史上的一桩公案。不过,若是我们从程序的角度上说,可以认为:马在这里表示一种类型,而白马,黑马它们的类型都是马。
Data types 构造数据类型:指针、数组、结构、类等 预定义数据类型(基本数据类型) 字符型:char 整型:int 单精度浮点型:float 双精度浮点型:double 无值型:void 布尔型:bool 构造数据类型:指针、数组、结构、类等
Data types 阅读程序:specify.cpp 类型修饰符 在基本数据类型(除void与bool类型外)前加上类型修饰符,来更具体地表示数据类型。 signed 有符号 unsigned 无符号 short 短型 long 长型 阅读程序:specify.cpp
Data types 类型修饰符说明 附件中带[ ]的部分表示是可以省略的,如short [int]可以写为short int 或简写为short,二者的含义是相同的。 四种修饰符都可以用来修饰整型和字符型。用signed修饰的类型的值可以为正数或负数,用unsigned修饰的类型的值只能为正数。 用short修饰的类型,其值一定不大于对应的整数,用long修饰的类型,其值一定不小于对应的整数。
Operators 算术运算符 运算符 功能 数据类型 例子 - 负号 数值 x=-y; + 加 z=x+y; 减 z=x-y; * 乘 / 除 z=x/y; % 求余 整数 z=x%y ++ 自加 z++或++z
Operators 赋值运算符 赋值运算符 例子 等价形式 = x=x+y += x+=y+z x=x+(y+z) -= x-=y+z *= x*=y+z x=x*(y+z) /= x/=y+z x=x/(y+z) %= x%=y+z x=x%(y+z)
Operators 关系运算符 关系运算符 含义 例子 < 小于 i>10 <= 小于或等于 (x+y)*2<=100 > 大于 x+y>z >= 大于或等于 x-y>=a*b+2 = = 等于 x+y==a+b != 不等于 x-y!=0
Operators 逻辑运算符 逻辑运算符 含义 例子 ! 逻辑非 !(x>10) && 逻辑与 (i>1) && (i<10) || 逻辑或 c==0 || c==9
Operators 三元运算符 在C++中只提供了一个三元运算符—即条件运算符“?:”,其一般形式为: 表达式1 ? 表达式2 : 表达式3 条件运算的规则是:首先判断表达式1的值,若其值为真(非0),则取表达式2的值为整个表达式的值;若其值为假(0),则取表达式3的值为整个表达式的值。
Operators 位运算符 运算符 含义 例子 & 按位与 i&128 | 按位或 j|64 ^ 按位异或 j^12 ~ 按位取反 ~j << 按位左移 i<<2 >> 按位右移 j>>2
Operators 复合位运算符 运算符 例子 等价形式 &= x&=y+z x=x&(y+z) |= x|=x+2 x=x|(x+2) ^= x^=y x=x^y <<= x<<=y+z x=x<<(y+z) >>= x>>=y+z x=x>>(y+z)
Operators 逗号运算符 逗号运算符的运算优先级是最低的。 一般形式为: 表达式1,表达式2,……,表达式N 在计算逗号表达式的值时,按从左至右的顺序依次分别计算各个表达式的值,而整个逗号表达式的值和类型是由最右边的表达式决定。
Operators Operator precedence 阅读程序:Mathops.cpp use parentheses to make the order of evaluation explicit A = X + Y – 2 / 2 + Z; X = 1、Y = 2、Z = 3 A = X + (Y – 2) / (2 + Z); 阅读程序:Mathops.cpp
Execution control statements 顺序结构 程序按照语句的书写顺序依次执行,语句在前的先执行,语句在后的后执行,只能满足设计简单程序的要求。 语句A 语句B
Execution control statements 分支结构 在分支结构中,程序根据判断条件是否成立,来选择执行不同的程序段。也就是说,这种程序结构,能有选择地执行程序中的不同程序段。 条件P 语句A 语句B
Execution control statements 分支结构 if-else语句 switch语句 switch(selector) { case integral-value1 : statement; break; case integral-value2 : statement; break; case integral-value3 : statement; break; (...) default: statement; }
Execution control statements 循环结构 在循环结构中,程序根据判断条件是否成立,来决定是否重复执行某个程序段。 真 假 条件P 语句A
Execution control statements 循环结构 while语句 do-while语句 for语句 跳转语句break 继续语句continue 关键字goto 阅读程序:Menu.cpp、Menu2.cpp、gotoKeyword.cpp
Execution control statements 递归算法 直接或间接地调用自身的算法称为递归算法。用函数自身给出定义的函数称为递归函数。 “老和尚讲故事” 要有终止条件,否则…… 阅读程序:CatsInHats.cpp
Execution control statements 递归算法 编写计算斐波那契数列的第n项函数fib(n): 斐波那契数列为:0、1、1、2、3、……,即: fib(0) = 0;fib(1) = 1; fib(n) = fib(n - 1) + fib(n - 2)(当n>1时) 写成递归函数为: int fib(int n){ if (n == 0) return 0; if (n == 1) return 1; if (n > 1) return fib(n - 1) + fib(n - 2); }
Execution control statements 递归算法 计算某个数的阶乘就是用那个数去乘包括 1 在内的所有比它小的数。 阶乘的一个有趣特性是,某个数的阶乘等于该数乘以比它小一的数的阶乘。 int factorial(int n) { return n * factorial(n - 1); } int factorial(int n) { if(n == 1) return 1; else return n * factorial(n - 1); }
Functions function prototyping int translate(float x, float y, flaoat z); empty argument list func()、func(void) uncertain argument list creating your own libraries
Introduction to pointers the ‘&’ operator precede the identifier name with ‘&’ and it will produce the address of that identifier. see “YourPets1.cpp” pointer definition For a type T , T * is the type “ pointer to T”, that is , a variable of type T * can hold the address of an object of type T.
Introduction to pointers The operator that defines a pointer ‘*’ Insert a star ‘*’ between the type and the identifier int* ip; // ip points to an int value int a = 47; int* ipa = &a; *ipa = 100;
Introduction to pointers the most basic use of pointers To change “outside objects” from within a function. Ordinarily, when you pass an argument to a function, a copy of that argument is made inside the function. This is referred to as pass-by-value. see “PassByValue.cpp”
Introduction to pointers want to modify the outside object pass a pointer into a function instead of an ordinary value, we are actually passing an alias to the outside object, enabling the function to modify that outside object. This is referred to as pass-by-address. see “PassAddress.cpp”
Introduction to C++ references Pointers work roughly the same in C and in C++, but C++ adds an additional way to pass an address into a function. This is pass-by-reference . see “PassReference.cpp”
Introduction to C++ references A reference is an alternative name for an object. we must initialize the reference while define it. int i = 1; int& r1 = i; // ok, r1 initialized int& r2; // error, miss initializer extern int& r3; // ok, r3 initialized elsewhere
Pointer to void void * : pointer to any type of object. int main() { void* vp; char c; int i; float f; double d; vp = &c; vp = &i; vp = &f; vp = &d; } ///:~
Pointer to void before you can use the pointer void *, you must cast it to the correct type int main() { int i = 99; void* vp = &i; // Can't dereference a void pointer: // *vp = 3; // Compile-time error // Must cast back to int before dereferencing: *((int*)vp) = 3; } ///:~
Scoping The scope of a variable extends from the point where it is defined to the first closing brace that matches the closest opening brace before the variable was defined. That is, a scope is defined by its “nearest” set of braces. see “Scope.cpp”
Defining variables on the fly C++ (not C) allows you to define variables anywhere in a scope, so you can define a variable right before you use it. Define variables inside the control expressions of for loops and while loops, inside the conditional of an if statement, and inside the selector statement of a switch.
Global variables Global variables are defined outside all function bodies and are available to all parts of the program (even code in other files). Global variables are unaffected by scopes and are always available see “Global.cpp” and “Global2.cpp”
Local variables register variables static variables The beauty of a static variable is that it is unavailable outside the scope of the function, so it can’t be inadvertently changed. see” Static.cpp” The second meaning of static is related to the first in the “unavailable outside a certain scope” sense. “file scope ” see “FileStatic.cpp” and “FileStatic2.cpp”
Constants and volatile #define PI 3.14159 The modifier const tells the compiler that a name represents a constant. Any data type, built-in or user-defined, may be defined as const. If you define something as const and then attempt to modify it, the compiler will generate an error. const float PI = 3.1415926;
Constants and volatile Whereas the qualifier const tells the compiler “This never changes” ,the qualifier volatile tells the compiler “You never know when this will change”.
Casting operators C Style 类型转换操作符 (type-id) expression int b=10; long a = (long) b; 函数调用语法 type-id( expression ) int b=10; long a = long(b);
Casting operators C++ Style-四个类型转换符 static_cast const_cast reinterpret_cast dynamic_cast
static_cast 用法:static_cast < type-id > ( expression ) 该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。 它主要有如下几种用法: ①用于类层次结构中基类和子类之间指针或引用的转换。 ②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。 ③把空指针转换成目标类型的空指针。 ④把任何类型的表达式转换成void类型。 see static_cast.cpp
const_cast see const_cast.cpp 用法:const_cast<type_id> (expression) 该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。 用法: 常量指针被转化成非常量指针,并且仍然指向原来的对象; 常量引用被转换成非常量引用,并且仍然指向原来的对象; 常量对象被转换成非常量对象。 see const_cast.cpp
see reinterpret_cast.cpp 用法:reinpreter_cast<type-id> (expression) type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。 它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数, 在把该整数转换成原类型的指针,还可以得到原先的指针值)。 see reinterpret_cast.cpp
dynamic_cast 用法:dynamic_cast < type-id > ( expression ) 该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *; 如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个引用。 dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
see sizeofOperator.cpp, sizeof.cpp tells us the number of bytes used by any particular variable an operator, not a function apply it to a variable you can use it without parentheses see sizeofOperator.cpp, sizeof.cpp
Composite type creation Aliasing names with “typedef ” Form : typedef existing-type-description alias-name Example: int* x, y; typedef int* IntPtr; IntPtr m, n;
Combining variables with struct The struct declaration must end with a semicolon. To select the elements of a particular struct object, use a ‘.’ a pointer to a struct object, you must select an element of that object using a different operator: the ‘->’ SimpleStruct2.cpp, SimpleStruct3.cpp
Clarifying programs with enum a way of attaching names to numbers enumerates any list of identifiers you give it by assigning them values of 0, 1, 2, etc enum ShapeType { circle = 10, square = 20, rectangle = 50 }; enum snap { crackle = 25, pop }; see Enum.cpp
Saving memory with union handle different types of data using the same variable two choices : create a struct containing all the possible different types you might need to store use a union. A union piles all the data into a single space see Union.cpp
Arrays select array elements starting at zero index past the end of the array, there is no safety net must define the size of the array at compile time and when you give the name of an array, without square brackets, what you get is the starting address of the array
谁能告诉我? 什么是QT?