C过度到C++
为什么要学C++
C++是由C语言升级而来, 它集成了C的效率和灵活.
C++是一系列"语言"的"结合体", 拥有多种编程范式和各种编程语言优点.编程范式
C++支持很多编程范式, 比如函数式, 基于对象, 面向对象, 模板元编程, 泛型等等.C++相对于C的新增特性
C++中增加了一些新的特性, 我们来看一看.
bool
C语言中的bool我们在使用的时候, 需要使用头文件 stdbool.h
而我们的C++中,这是原生支持的数据类型.原生bool和C里边的bool的区别
在原生bool类型中, 0 表示 false, !0 表示 true, 它是原生的.
而在C中的bool, 0 表示 false, 1 表示 true, 它是使用#define定义的.
以 `-1` 这个值来举例在原生bool中, -1为true, 是
定义的行为.
而在非原生bool中, -1为未定义的行为.
虽然最终的结果可能是正确的, 但是, 这是因为编译器在进行布尔运算的时候, 替我们进行了大量操作.
头文件
我们的C++是由C进化发展而来
它具有几个标准
我们使用 .h 头文件, 说明它是由C继承来的, 符合C标准
#include <stdio.h>
而使用 cXXX, 说明它是由C集成来的, 并且符合C++标准#include <cstdio>而使用我们的无后缀名的头文件, 说明是我们的
C++标准库
#include <iostream>
预编译头
"预编译头"是VC独有的, 是属于微软提供的"便利".
它不被C++标准所承认.VS中可以设置是否使用"预编译头".
新的 printf
在C++中, 我们使用 std::cout 来代替 printf 函数.
需要加上 #include <iostream> 头文件哦~// 举个例子
#include <iostream>
int main()
{
int num = 20;
std::cout << num;
std::cout << "Hello CPP!";
return 0;
}域运算符(Domain Operator)
我们来看一下这个例子// 域运算符例子
#include <iostream>
// 定义全局变量
int num = 100;
int main()
{
// 局部变量
int num = 20;
std::cout << "局部变量:";
std::cout << num;
std::cout << "全局变量:"
std::cout << ::num;
return 0;
}
::就是域运算符, 它可以访问指定命名空间的变量.当我们的 域运算符 为空的时候, 代表的是 全局域
当我们的 域运算符 前有指定的时候, 这个指定就是命名空间比如我们例子中的
std::,std就是一个命名空间.
命名空间
命名空间可以使用namespace来进行声明.
举个例子// 域运算符例子
#include <iostream>
using namespace std;
// 定义全局变量
int num = 100;
namespace Hades
{
int num = 50;
}
int main()
{
// 局部变量
int num = 20;
cout << "局部变量:";
cout << num;
cout << "全局变量:"
cout << ::num;
cout << "Hades命名空间变量:"
cout << Hades::num;
return 0;
}使用
using关键字可以指定使用的命名空间.比如
using namespace std;表示默认使用 std 命名空间.
那么, 在使用 std::cout 的时候, 就不需要在加 命名空间 的名字了.
多个命名空间重名的情况这里暂不讨论.
new 和 delete
对
堆空间进行操作.
对应C语言中的函数为 malloc 和 free
// 例子
#include <iostream>
using namespace std;
int main()
{
// 声明一个int的指针, 并将指针所指向的值设置为100
int *pNum = new int(100);
cout << *pNum;
// 千万不要忘了delete
delete pNum;
// 在堆上进行分配int数组, 长度为10
int *pArray = new int[10];
// 注意, 上面那句话, 数组数据并未初始化.
// 删除的时候, 需要使用数组方式删除
delete[] pArray;
return 0;
}new 和 delete是运算符, 而malloc 和 free是函数!
重载 overload
重载是C++中是一个非常强大的机制.
// 重载例子
#include <cstdio>
void HadesCout(int num)
{
printf("%d", num);
}
void HadesCout(char* szStr)
{
printf("%s", szStr);
}
void HadesCout(char c)
{
printf("%c", c);
}
void HadesCout(double dNum)
{
printf("%f", dNum);
}
int main()
{
HadesCout("Hello C++\n");
HadesCout(100);
HadesCout(10.0);
HadesCout('H');
return 0;
}
函数名相同, 但是它的参数表的个数或顺序,类型不同, 构成重载!返回值不同不能构成重载.函数名相同, 参数表个数,类型,顺序都相同, 参数名称不同, 会造成函数重定义.
// 注意
// 参数类型是值的参数的类型, 而不是参数的名称.
// 比如:
int func(int a);
void func(int b);
// 这两个是不构成重载的, 它会造成函数重定义!
// ==================================
// 参数个数相同, 类型顺序不同, 也会重载.
// 比如
int func(int a, char c);
int func(char c, int a);
// 这两个是构成重载的!此处场景前提: 无Class, 无多个命名空间, 只有1个CPP文件.
重载的原理(仅在易于理解方面)
重载函数的生成, 实际上是分成了几个不同的函数.
虽然函数名相同, 但是函数地址不同.
这个工作是由编译器帮我们做的.
每个函数空间都是独立的.
编译器记录了一个符号表.
包括了函数的参数, 变量, 类型等信息.
在调用的时候进行匹配, 然后再去调用.
命名粉碎(命名重定向)
由于
重载机制, 在我们编译的过程中, 函数名称会发生改变.
在我们项目内部调用的时候, 因为我们的编译器有记录符号表, 所以调用正常.
但是在我们提供给外部进行调用的时候(比如编译成dll), 我们的函数名就会发生变化, 从而导致调用失败.
这里不进行详细研究, 我们只做一个了解.
最常用的解决办法, 是使用
extern "C" { /* 各种语句 */ }的方式进行编译.
未完待续如有错误,请提出指正!谢谢.
本文由 花心胡萝卜 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: 2017-01-04 at 01:49 am