从C过渡到C++

来源:互联网 发布:淘宝客工具箱 编辑:程序博客网 时间:2024/05/21 06:33

## C++基础1:从C过渡到C++


>     C plus plus -- C语言的超级/带Class的C语言
    C++可以完全引用C/C不能直接调用C++

### 案例:输出Hello World

* 源代码:`HelloWorld.cpp`
``````
#include <iostream>
using namespace std;
int main(){
    cout << "Hello world" << endl;
}
``````
* 编译:`g++ HelloWorld.cpp -o HelloWorld`
* 运行:`./HelloWorld`
* 结果:`Hello world`

从`HelloWorld.cpp`,看C++与C的基本区别:
1. 文件后缀`.cpp`
2. 头文件`#include <iostream>`
3. 命名空间 `using namespace std;`
4. 标准输出`cout`、输出运算符`<<`、换行`endl`
5. 编译工具`g++`

> `g++`安装:`yum install gcc-c++`

---

#### 1.源文件后缀

* C/C++后缀名区别

|C|C++|
|:-|:-|
|`*.c`|`*.cpp` `*.cc` `*.cxx`|

* 不同编译器C++后缀名区别

|平台|可用后缀名|
|:-|
|Unix|`*.C`, `*.cc`, `*.cxx`, `*.c`|
|GNU C++|`*.C`, `*.cc`, `*.cxx`, `*.cpp`, `*.c++`|
|Borland C++|`*.cpp`|
|Microsoft Visual C++|`*.cpp`, `*.cxx`, `*.cc`|

---

#### 2.引用头文件

C++头文件使用C标准库,在C标准库文件名前加上字母`c`,并且省略后缀名`.h`,例如:

|C|C++|
|:-|:-|
|`#include <stdio.h>`|`#include <iosteam>` /`#include <cstdio>`|
|`#include <stdlib.h>`|`#include <cstdlib>`|
|`#include <string.h>`|`#include <cstring>`|
|`#include <math.h>`|`#include <cmath>`|

*有些C++编译器同时支持以上两种头文件,但有些不。请使用C++标准方式*

---

#### 3.函数重载(overload)  

实验:以下C与C++的编译执行结果
* `printf.c`
```
#include <stdio.h>
void printf(){
    printf("Hello world");
}
int main(){
    printf();
}
```
gcc printf.c -o print
print.c:3:6: error: conflicting types for ‘printf’
 void printf(){

* `printf.cpp`
```
#include <cstdio>
void printf(){
    printf("Hello world");
}
int main(){
    printf();
}
```
编译运行成功

函数重载:函数名相同只有参数(个数或者类型)不相同。

|C|C++|
|:-|:-|
|不支持重载|支持重载|

---

#### 4. 命名空间 

实验:以下C的编译结果
* `scope.c`
```
#include <stdio.h>
void test(){
    printf("this is test\n");
}
void test(){
    printf("this is another test\n");
}
int main(){
    test();
}
```
gcc scope.c -o scope
scope.c:9:6: error: redefinition of ‘test’
 void test(){
      ^
scope.c:3:6: note: previous definition of ‘test’ was here
 void test(){

作用域

|C|C++|
|:-|:-|
|文件、函数、复合语句|命名空间、文件、类作用域、函数、复合语句|

命名空间

|C|C++|
|:-|:-|
|不支持命名空间|支持命名空间|

* 命名空间的作用:避免全局变量、函数、类的命名冲突(因为名字相同而编译失败)

* 定义命名空间
``````
namespace 空间名 {

}
``````
* 引用命名空间
``````
using namespace 空间名;
``````
* 标准命名空间`std`
``````
using namespace std;
``````

C++命名空间处理方式
``````
#include <cstdio>
namespace scope1 {
        void test(){
            printf("this is test\n");
        }
}
namespace scope2{
void test(){
        printf("this is another test\n");
    }
}
int main(){
    scope1::test();
    scope2::test();
}
```

* 命名空间嵌套
```
namespace A {
  void test1();
  namespace B {
    void test2();
    namespace C {
      void test3();
    }
  }
}
```

在命名空间`A`外访问
```
A::test1();
A::B::test2();
A::B::C::test3();
```

在命名空间`A`内访问
```
test1();
B::test2();
B::C::test3();
```

在命名空间`B`内访问
```
test1();
test2();
C::test3();
```

在命名空间`C`内访问
```
test1();
test2();
test3();
```

```
namespace A {
  void test();
  namespace B {
    void test();
    namespace C {
      void test();
    }
  }
}
```

在命名空间`A`外访问
```
A::test();
A::B::test();
A::B::C::test();
```

在命名空间`A`内访问
```
test();
B::test();
B::C::test();
```

在命名空间`B`内访问
```
test();
C::test();
```

在命名空间`C`内访问
```
test();
```

> 命名空间可以嵌套,类定义是否嵌套?结构体/联合体定义是否可以嵌套?函数定义是否可以嵌套?复合语句(if-else for while do-while)是否可以嵌套?

```
class A{
    class B{
    };
}
```

```
void test1(){
    int test2(){
    }
}
```

* 命名空间可以重复定义

```
namespace A{
  void test1();
  // ...
}

namespace A{
  void test2();
  // ...
}
```

全局命名空间/默认命名空间/匿名命名空间:所有没有定义命名空间的函数都在全局命名空间内。
比如: main()函数,使用<stdio.h>。

命名空间没有生存周期,作用域是全局。

命名空间可以限制所有标识符(变量名、函数名、类名、空间名、类型名(typedef)),宏定义不受命名空间限制。

---

#### 5. 类型 

* 新增基本类型`bool`--`true`/`false`
 * `password.c`
```
#include <stdio.h>
int main(){
      printf("input user name:");
      char name[BUFSIZ];
      scanf("%s",name);
      printf("input 3 number password:");
      int password1;
      scanf("%d",&password1);
      printf("input 3 number password again:");
      int password2;
      scanf("%d",&password2);
      printf("password check:%d\n", password1 == password2);  //ture:1;false:0;
}
```
 * `password.cpp`
```
#include <iostream>
#include <cstdio>
using std::cout;
using std::cin;
using std::endl;
int main(){
      cout << "input user name:";
      char name[BUFSIZ];
      cin >> name;
      cout << "input 3 number password:";
      int password1;
      cin >> password1;
      cout << "input 3 number password again:";
      int password2;
      cin >> password2;
      cout << "password check:" << (password1 == password2) << endl;
}
```

* 新增自定义类型`class`
详细信息参见:类与对象章节

* C++的新增关键`and` `or` `not`

```
if(a>b && c<d){

}
```

```
if(a>b and c<d){

}
```

在C语言中`iso646.h`定义了这些宏定义。

---

#### 6. 思想

|C|C++|
|:-|:-|
|面向过程|面向对象/基于对象、模板/泛型编程|

何为面向过程?何为面向对象?
* 面向过程:强调如何处理,通常是自下而上。
* 面向对象:强调执行处理的对象,通常是自上而下。

> 面向过程与面向过程、厨师与老板

#### 7. 动态内存

* 基本类型的动态内存
 * `dynamic_mem.c`
```
#include <stdio.h>
#include <stdlib.h>
int main(){
      int* num = malloc(sizeof(int));
      *num = 100;
      printf("%d\n",*num);
      free(num);
}
```
 * `dynamic_mem.cpp`
```
#include <iostream>
int main(){
      int* num = new int;
      *num = 100;
      std::cout << *num << std::endl;
      delete num;
}
```

标量:单个值(基本类型(int、float、char)/复合类型(数组、指针、引用))/向量:多个值(类、结构体、联合体等)

> `new` `delete`都是关键字,用于申请/释放堆内存。

动态内存区别

|C|C++|
|:-|:-|
|`malloc()`/`free()`|`new`/`delete`|

*C++仍然可以使用`malloc()`/`free()`,但是不建议这么做。*

问题:
* `malloc()`申请内存,是否可以使用`delete`销毁内存?
* `new`申请内存,是否可以使用`free()`销毁内存?
答:不能,malloc /free主要为了兼容C,new和delete 完全可以取代malloc /free的。malloc /free的操作对象都是必须明确大小的。而且不能用在动态类上。new 和delete会自动进行类型检查和大小,malloc/free不能执行构造函数与析构函数,所以动态对象它是不行的。当然从理论上说使用malloc申请的内存是可以通过delete释放的。不过一般不这样写的。而且也不能保证每个C++的运行时都能正常。

> 注意:`delete`和`free()`动态内存后,指针指向`NULL`