C++对C的加强
程序设计方法的发展历程
面向过程的结构化程序设计方法。 |
自 顶向下、逐步求精。 |
面向对象的方法 |
封装、继承、多态 |
把对象的属性和操作封装起来,形成一个类;类是一个抽象的概念;class |
C语言和C++语言关系 |
C语言是在实践的过程中逐步完善起来的 C语言的目标是高效 C语言 + 面向对象方法论===》Objective C /C++ |
每一个程序员都不能固步自封,要多接触新的行业、新的技术领域。暂新的突破自我 |
namespace概念及Register的变化
namespace概念 |
在C语言中只有一个全局作用域 在C语言中只有一个全局作用域 std是c++标准命名空间,c++标准程序库中的所有标识符都被定义在std中,比如标准库中的类iostream、vector 可以更好地控制标识符的作用域 |
1) 当使用<iostream>的时候,该头文件没有定义全局命名空间,必须使用namespace std;这样才能正确使用cout。若不引入using namespace std ,需要这样做。std::cout。 2) c++标准为了和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。 3) C++命名空间的定义: namespace name { … } 4) using namespace NameSpaceA; 5)namespce定义可嵌套。
|
namespace NameSpaceA { int a = 0; } namespace NameSpaceB { int a = 1; namespace NameSpaceC { struct Teacher { char name[10]; int age; }; } } int main() { using namespace NameSpaceA; using NameSpaceB::NameSpaceC::Teacher; printf("a = %d\n", a); printf("a = %d\n", NameSpaceB::a); Teacher t1 = {"aaa", 3}; printf("t1.name = %s\n", t1.name); printf("t1.age = %d\n", t1.age); system("pause"); return 0; }
|
Register |
//register关键字 请求编译器让变量a直接放在寄存器里面,速度快 //在c语言中 register修饰的变量 不能取地址,但是在c++里面做了内容
/* //1 register关键字的变化 register关键字请求“编译器”将局部变量存储于寄存器中 C语言中无法取得register变量地址 在C++中依然支持register关键字 C++编译器有自己的优化方式,不使用register也可能做优化 C++中可以取得register变量的地址
//2 C++编译器发现程序中需要取register变量的地址时,register对变量的声明变得无效。
//3 早期C语言编译器不会对代码进行优化,因此register变量是一个很好的补充。
*/ |
函数检测增强
/* 在C语言中,重复定义多个同名的全局变量是合法的 在C++中,不允许定义多个同名的全局变量 C语言中多个同名的全局变量最终会被链接到全局数据区的同一个地址空间上 int g_var; int g_var = 1;
C++直接拒绝这种二义性的做法。 */
|
int main(int argc, char *argv[]) { printf("g_var = %d\n", g_var); return 0; } |
struct类型加强
struct类型的加强: C语言的struct定义了一组变量的集合,C编译器并不认为这是一种新的类型 C++中的struct是一个新类型的定义声明 |
struct Student { char name[100]; int age; }; int main(int argc, char *argv[]) { Student s1 = {"wang", 1}; Student s2 = {"wang2", 2}; return 0; } |
C++中所有的变量和函数都必须有类型
f(i) { printf("i = %d\n", i); } g() { return 5; } int main(int argc, char *argv[]) { f(10); printf("g() = %d\n", g(1, 2, 3, 4, 5)); getchar(); return 0; } |
总结: /* 在C语言中 int f( );表示返回值为int,接受任意参数的函数 int f(void);表示返回值为int的无参函数 在C++中 int f( );和int f(void)具有相同的意义,都表示返回值为int的无参函数 */ C++更加强调类型,任意的程序元素都必须显示指明类型 |
/* C++中的布尔类型 C++在C语言的基本类型系统之上增加了bool C++中的bool可取的值只有true和false 理论上bool只占用一个字节, 如果多个bool变量定义在一起,可能会各占一个bit,这取决于编译器的实现
true代表真值,编译器内部用1来表示 false代表非真值,编译器内部用0来表示
bool类型只有true(非0)和false(0)两个值 C++编译器会在赋值时将非0值转换为true,0值转换为false
*/ |
三目运算符增强
int main() { int a = 10; int b = 20; //返回一个最小数 并且给最小数赋值成3 //三目运算符是一个表达式 ,表达式不可能做左值 (a < b ? a : b )= 30; printf("a = %d, b = %d\n", a, b); system("pause"); return 0; }
1)C语言返回变量的值 C++语言是返回变量本事 2) C语言中的三目运算符返回的是变量值,不能作为左值使用 C++中的三目运算符可直接返回变量本身,因此可以出现在程序的任何地方 注意: 3) 三目运算符可能返回的值中如果有一个是常量值,则不能作为左值使用 (a < b ? 1 : b )= 30; 4)C语言如何支持类似C++的特性那? 变量的本质是内存空间的别名,是一个标号。
|
C++对C函数增强
内联函数
1)内联函数在编译时直接将函数体插入函数调用的地方 2)inline只是一种请求,编译器不一定允许这种请求 3)内联函数省去了普通函数调用时压栈,跳转和返回的开销 |
默认参数 函数默认参数的规则 只有参数列表后面部分的参数才可以提供默认参数值 一旦在一个函数调用中开始使用默认参数值,那么这个参数后的所有参数都必须使用默认参数值
|
/* 函数占位参数 占位参数只有参数类型声明,而没有参数名声明 一般情况下,在函数体内部无法使用占位参数 */ |
默认参数和占位参数 int func(int a, int b, int = 0) { return a + b; } int main66(int argc, char *argv[]) { printf("func(10, 20) = %d\n", func(10, 20)); printf("Press enter to continue ..."); getchar(); return 0; } |
函数重载
用同一个函数名定义不同的函数 当函数名和不同的参数搭配时函数的含义不同 函数重载至少满足下面的一个条件: 参数个数不同 参数类型不同 参数顺序不同 */ |
//当函数默认参数遇上函数重载会发生什么 /* int func(int a, int b, int c = 0) { return a * b * c; } int func(int a, int b) { return a + b; } int main() { int c = 0; c = func(1, 2); // 存在二义性,调用失败,编译不能通过 printf("c = %d\n", c); printf("Press enter to continue ..."); getchar(); return 0; } */
/* 编译器调用重载函数的准则 将所有同名函数作为候选者 尝试寻找可行的候选函数 精确匹配实参 通过默认参数能够匹配实参 通过默认类型转换匹配实参 匹配失败 最终寻找到的可行候选函数不唯一,则出现二义性,编译失败。 无法匹配所有候选者,函数未定义,编译失败。 */
/* 函数重载的注意事项 重载函数在本质上是相互独立的不同函数(静态链编) 重载函数的函数类型是不同的 函数返回值不能作为函数重载的依据 函数重载是由函数名和参数列表决定的。 */
//重载和函数指针结合
/* 函数重载与函数指针 当使用重载函数名对函数指针进行赋值时 根据重载规则挑选与函数指针参数列表一致的候选者 严格匹配候选者的函数类型与函数指针的函数类型 */ /* int func(int x) // int(int a) { return x; } int func(int a, int b) { return a + b; } int func(const char* s) { return strlen(s); } typedef int(*PFUNC)(int a); // int(int a) int main(int argc, char *argv[]) { int c = 0; PFUNC p = func; c = p(1); printf("c = %d\n", c); printf("Press enter to continue ..."); getchar(); return 0; } */ |
函数重载与函数指针 当使用重载函数名对函数指针进行赋值时 根据重载规则挑选与函数指针参数列表一致的候选者 严格匹配候选者的函数类型与函数指针的函数类型
|
面向过程编程到面向对象编程训练
#include "iostream" using namespace std; //目标:抽象立方体 求立方体的s 和 v class Cube { public: void setA(int a) { m_a = a; } int getA() { return m_a; } void setB(int a) { m_a = a; } int getB() { return m_b; } void setC(int a) { m_a = a; } int getC() { return m_c; } void setABC(int a=0, int b=0, int c=0) { m_a = a; m_b = b; m_c = c; } public: int getS() { m_s = 2*(m_a*m_b + m_a*m_c + m_b*m_c); return m_s; } int getV() { m_v = m_a*m_b*m_c; return m_v; } public: char * cubeEqueal(Cube &c1, Cube &c2) { if (c1.getA()== c2.getA() && c1.getB()== c2.getB() && c1.getC()== c2.getC()) { return "相等"; } return "不相等"; } char * cubeEqueal(Cube &c2) { if (m_a== c2.getA() && m_b== c2.getB() && m_c== c2.getC()) { return "相等"; } return "不相等"; } private: int m_a; int m_b; int m_c; int m_v; int m_s; }; void main34() { Cube cube1, cube2, cube3; cube1.setABC(1, 2, 3); cube2.setABC(2, 3, 4); cube3.setABC(1, 2, 3); //cout<<cube1.cubeEqueal(cube1, cube2); cout<<cube1.cubeEqueal(cube2); cout<<cube1.cubeEqueal(cube1); //cout<<cubeEqueal(cube1, cube2)<<endl; //cout<<cubeEqueal(cube1, cube3)<<endl; system("pause"); } void main31() { Cube cube1; cube1.setABC(1, 2, 3); cube1.getV(); cube1.getS(); cout<<"体积为:"<<cube1.getV()<<"面积为"<<cube1.getS(); system("pause"); } //全局函数 char * cubeEqueal(Cube &c1, Cube &c2) { if (c1.getA()== c2.getA() && c1.getB()== c2.getB() && c1.getC()== c2.getC()) { return "相等"; } return "不相等"; } void main33() { Cube cube1, cube2, cube3; cube1.setABC(1, 2, 3); cube2.setABC(2, 3, 4); cube3.setABC(1, 2, 3); cout<<cubeEqueal(cube1, cube2)<<endl; cout<<cubeEqueal(cube1, cube3)<<endl; system("pause"); } |
const专题讲座
const int a; int const b;
const int *c; int * const d; const int * const e ;
含义: //第一个第二个意思一样 代表一个常整形数 //第三个 c是一个指向常整形数的指针(所指向的内存数据不能被修改,但是本身可以修改) //第四个 d 常指针(指针变量不能被修改,但是它所指向内存空间可以被修改) //第五个 e一个指向常整形的常指针(指针和它所指向的内存空间,均不能被修改) |
结论: C语言中的const变量 C语言中const变量是只读变量,有自己的存储空间 C++中的const常量 可能分配存储空间,也可能不分配存储空间 当const常量为全局,并且需要在其它文件中使用 当使用&操作符取const常量的地址 符号表、编译过程中若发现对const使用了extern或者&操作符,则给对应的常量分配存储空间(兼容C) |
int main() { const int a = 10; int *p = (int*)&a; printf("a===>%d\n", a); *p = 11; printf("a===>%d\n", a); printf("Hello......\n"); return 0; } |
C++中的const常量类似于宏定义 const int c = 5; ≈ #define c 5 C++中的const常量在与宏定义不同 const常量是由编译器处理的,提供类型检查和作用域检查 宏定义由预处理器处理,单纯的文本替换 |
引用专题讲座
1、 引用是C++的概念,属于C++编译器对C的扩展 int main() { int a = 0; int &b = a; //int * const b = &a b = 11; //*b = 11; return 0; } |
2、 普通引用有自己的空间吗? struct Teacer { int &a; int &b; }; int main() { printf("sizeof(Teacher) %d\n", sizeof(Teacer)); system("pause"); return 0; } |
3、 //当实参传给形参引用的时候,只不过是c++编译器帮我们程序员手工取了一个实参地址,传给了形参引用(常量指针) |
乐享:知识积累,快乐无限。