C和C++
- 1.类和结构体的关系:
- 2.面向对象和面向过程
- 3.头文件和标准命名空间
- 4.cin和cout
- 5. const在C++中和C中的区别
- 6.const全局作用域
- 7 new和delete
- 8 内联函数
- 9 函数重载
- 10. 函数重载的匹配
引用:
[1]C语言中文网
1.类和结构体的关系:
类是结构体的升级表现,结构体只能封装变量,类不仅可以封装变量,还可以封装函数。使得具有耦合关系的变量和函数统一管理。
2.面向对象和面向过程
面向对象是在面向过程的基础上,进一步的封装。
(图片引用自C语言中文网)
不要把面向对象和面向过程对立起来。面向对象在执行效率上没有明显优势,但是有利于多人配合的大型代码管理。
3.头文件和标准命名空间
带c的头文件,例如cstdio、cstdlib。都是原C语言头文件。引用方式:#include < cstdio>
后缀带.h的头文件,例如stdio.h、stdlib.h,iostream.h、fstream.h 都是老式C++语言的头文件,没有使用任何命名空间,所有符号都位于全局作用域。引用方式:#include <stdio.h>
后缀不带.h的头文件,例如stdio、stdlib、iostream、fstream,都是新式统一修改过的C++语言的头文件,头文件的内容在命名空间 std 中。引用方式:#include < iostream>
4.cin和cout
cout 和 cin 分别是ostream和istream的C++内置对象,而不是关键字,在标准库中提前实例化。这种提前创建的对象被称为内置对象。
5. const在C++中和C中的区别
从上述两幅图中可以看出,在C++语言中const修饰的常量类似于#define的操作,直接替换,无需读取内存数据。它和#define的区别在于,#define是在预处理阶段就替换,const是在编译阶段就替换。
而C语言中const修饰的常量是由对应数据存储的,每次使用常量,会先读取对应内存地址中的数据,然后使用。
补充其他两个知识点:
- &n得到的是const int类型指针,需要进行(int*)强制类型转化。
- const修饰的常量在C语言中其实是可以通过指针修改的。
在C++语言中,#define和const的区别。#define仅是字符串的替换,不会做类型检查。而const是有类型的,可以做类型检查。
6.const全局作用域
普通全局变量的作用域是当前文件,但是在其他文件中也是可见的,使用extern声明后就可以使用
(图片引用自C语言中文网)
但是注意:C++对于const的特性做了修改,对于const修饰的常量,对于当前文件时可见的,但是对于其他文件不可见,这和添加了static关键字的效果类似。
由于该特性,建议讲const修饰的常量放在头文件中,这样就可以多文件多次使用。
C和C++中全局 const 变量的作用域相同,都是当前文件,不同的是它们的可见范围:C语言中 const 全局变量的可见范围是整个程序,在其他文件中使用 extern 声明后就可以使用;而C++中 const 全局变量的可见范围仅限于当前文件,在其他文件中不可见,所以它可以定义在头文件中,多次引入后也不会出错。
7 new和delete
在C语言中,会用malloc()来申请动态内存,用free()来释放内存
int *p = (int*)malloc(sizeof(int) * 10);
free(p);
在C++语言中,会用new[]来申请动态内存,用delete[]来释放内存。
int *p = new int;
delete p;
int *p = new int[10];
delete[] p;
不论是C++中的new还是C中的malloc(),申请的内存都是存放在堆区,并且必须配合delete或者free()进行释放,否则会造成内存泄漏。
8 内联函数
作用:内联函数主要有两个作用,一是消除函数调用时的开销,二是取代带参数的宏
程序在执行一个函数之前需要做一些准备工作,要将实参、局部变量、返回地址以及若干寄存器都压入栈中,然后才能执行函数体中的代码;函数体中的代码执行完毕后还要清理现场,将之前压入栈中的数据都出栈,才能接着执行函数调用位置以后的代码。(引用自C语言中文网)
要在函数定义处添加 inline 关键字,在函数声明处添加 inline 关键字是无效的。
当函数非常复杂的时候,时空开销忽略不计,因此只是将短小的函数声明为内联函数
宏定义如果带参数的话经常会出现很多程序bug(因为只是简单的字符串替换,没有类型检查和数据检查),用内联函数就很好的规避这些问题。
9 函数重载
作用:重载是在一个作用范围内,例如一个类或者命名空间中,存在多个命名相同但参数列表不同的函数,从而可以让相同名称的函数实现不同的功能(但是功能务必相似)。
规则:
- 函数名称必须相同。
- 函数的参数列表必须不同。(类型不同,个数不同,顺序不同等,但是仅仅参数名称不同是不可以的)
- 返回值可以是相同也可以是不同。
- 仅仅函数返回值不同不能作为重载依据。
函数重载仅仅是语法层面的,本质上它们还是不同的函数,占用不同的内存,入口地址也不一样。
10. 函数重载的匹配
函数重载本质上还是不同的函数,每次调用函数时,编译器就会通过参数列表匹配到对应的函数,其优先级详见下述图片,具体优先级分别为:精准匹配>类型提升>类型转化。如果匹配成功则终止,不再往下匹配。
(图片引用自C语言中文网)
在参数过少,或者过多的时候就会出现函数参数的二义性。比如:参数中都属于类型转化优先级,则会出现编译器不知道如何处理的情况。
类型转化和类型提升不一样。类型提升是积极的,是为了适应计算机硬件的,可以提升效率。类型转化是不得已的,是消极的。