C++超详细梳理基础知识

目录
  • 命名空间的使用
    • 来源
    • 命名空间的使用
      • 不展开
      • 部分展开
      • 全展开
    • 函数重载
      • 函数重载的规则
      • C++如何实现函数重载
  • 引用

命名空间的使用

来源

在了解命名空间的原理和使用之前,我们先要理解,命名空间是为了解决什么问题。

C++是在C的基础上发展而形成的一种语言,完全兼容C的语法,也加入了许多新的规则和语法来解决C的缺陷。

命名空间就是为了解决C语言中的重复命名的问题。

首先我们来看看这么一个代码:

#include<stdio.h>
int main()
{
	int scanf = 20;
	printf("%d", scanf);
	return 0;
}

我们都知道scanf在C之中是一个函数名,但诡异的是我们在主函数中声明scanf是有效的并且输出结果是20.

在这个程序内的scanf就是表示是一个int型整数,这是根据就近原则或者说是局部优先原则确定的。

接下来我们看看另一个程序:

#include<stdio.h>
int main()
{
	int scanf = 20;
	scanf("%d", &scanf);
	printf("%d", scanf);
	return 0;
}

在我们想要scanf作为函数使用时出现了问题,两者之间命名冲突。

在C语言中我们被告诫不要让变量名与函数名冲突,但是在C++中有没有合适的解决方法呢?

命名空间的使用

我们先来书写一个在C++中最为简单的程序:

#include<iostream>
using namespace std;
int main()
{
	cout << "hello  world" << endl;
	return 0;
}

这里我们就看到了namespace命名空间,但是现在它是用来干什么的我们还不清楚,首先我们先来了解一下它。

一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。

让我们从代码方面来看看命名空间到底是什么:

#include<iostream>
using namespace std;
namespace  N1
{
	int printf = 30;
	int strlen = 20;
}
int main()
{
	cout << "hello  world" << endl;
	cout << N1::printf << endl;
	return 0;
}

我们声明了一个命名空间N1,在内部声明了两个int类型的变量,通过作用域限定符::我们就可以调用命名空间中的变量。

并且命名空间中也可以嵌套命名空间:

namespace  N1
{
	int printf = 30;
	int strlen = 20;
	namespace  N2
	{
		int a = 0;
	}
}

通过上面的解释,我们明白了,命名空间适用于将声明的名称之间相互隔离,防止命名冲突。比如说,我们调用N1::printf时,::将范围限定在N1这个命名空间之中,而不会与函数名printf冲突,反之亦然。

那么一开始我们看到的那个程序是什么意思呢?

我们先来看另一个版本的程序:

int main()
{
	std::cout << "hello  world" << std::endl;
	//cout << N1::printf << endl;
	return 0;
}

显然std也是一个命名空间,通过作用域限定符调用命名空间std内的内容。

那么一开始的

using namespace std;

是用来干嘛的呢?

using的作用是把命名空间中的内容在全局空间中展开,命名空间中的变量就成为了全局变量,调用时就不需要命名空间名加上作用域限定符了。

实际上命名空间有三种使用方式,各有优劣。

不展开

也就是

std::cout << "hello  world" << std::endl;

的方式,要使用命名空间中的名称,就要使用::来限定命名空间,完全避免了冲突,在大工程中使用。缺点就是在日常练习中书写代码较为繁琐。

部分展开

使用using将命名空间中成员引入,将一些我们常用的符号在全局中展开,就可以大大简化代码,是在第一个方法和第三个方法之间取一个折中。

using std::cout;
using std::endl;
int main()
{
	cout << "hello  world" << endl;
	//cout << N1::printf << endl;
	return 0;
}

全展开

使用using namespace 命名空间名称引入:

using namespace std;
int main()
{
	cout << "hello  world" << endl;
	//cout << N1::printf << endl;
	return 0;
}

这个方法是有问题的,相当于一夜回到解放前。好不容易搞个命名空间隔离了,结果一行代码全给展开了,直接在全局空间声明,完全没有防止命名冲突的作用,只在日常练习中使用。

函数重载

函数重载的规则

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。

比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!”

函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数 个数 或 类型 或 顺序)必须不同,常用来处理实现功能类似数据类型不同的问题。

比如下面的相加函数:

int Add(int left, int right)
{
return left+right;
}
double Add(double left, double right)
{
return left+right;
}
long Add(long left, long right)
{
return left+right;
}
int main()
{
Add(10, 20);
Add(10.0, 20.0);
Add(10L, 20L);
return 0;
}

虽然函数名相同,但是所带参数的类型不同,所以在调用的时候能够调用不同的函数定义,让函数的使用更加灵活。

这里要特别注意的是函数重载的规则:同名函数的形参列表(参数 个数 或 类型 或 顺序)必须不同。

short Add(short left, short right)
{
return left+right;
}
int Add(short left, short right)
{
return left+right;
}

那么两个同名函数,算不算是函数重载呢,显然他们的形式参数的个数 ,类型以及 顺序都是一样的,只是返回类型不同,不构成重载函数。

C++如何实现函数重载

我们都知道C是没有函数重载这个功能的,那么C++是怎么实现的呢?

其实是通过C++的函数名修饰来实现函数重载的。

大家这里可能有一些迷糊,这需要我们对代码的编译过程有一定的了解:

C和C++的区别在于,在编译的符号汇总中,C语言是使用函数的原名进行汇总的,导致了一个名称只能对应一个函数,所以不能进行函数重载。

但是在C++中,符号汇总起来的是经过修饰的函数名,即使原名称一样,由于参数 个数 或 类型 或 顺序不同,经过修饰后的符号名也不同,比如说:

int Add(int left, int right)
{
return left+right;
}

double Add(double left, double right)
{
return left+right;
}

long Add(long left, long right)
{
return left+right;
}

比如说这三个函数经过函数名修饰之后就变成了——Addii、Adddd、Addll。于是我们在后续的使用中就可以很好地区分这三个函数了,即使在我们看来这三个函数名是一样的,但是在计算机看来这三个完全就是三个不一样的函数。

引用

引用可以说就是给变量取别名。是怎么实现的呢?

#include<iostream>
int main()
{
	int a = 0;
	int b = 0;
	int& c = a;
	c = 10;
	return 0;
}

其中 int& c = a; 就是把c作为a的别名,这时c和a指向的内存空间是同一块。

当改变c的值时,a中的值同时改变。

但是,在使用过程中也有一些需要注意的事项——

1.引用类型必须和引用实体是同种类型的

2.引用在定义时必须初始化

int a;
int& b = a;

3.一个变量可以有多个引用

int a = 0;
int& b = a;
int& c = a;
int$ d = c;

4.引用一旦引用一个实体,再不能引用其他实体

#include<iostream>
int main()
{
	int a = 0;
	int b = 0;
	int& c = a;
	int& c = b;
	c = 10;
	return 0;
}

到此这篇关于C++超详细梳理基础知识的文章就介绍到这了,更多相关C++基础内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++数据结构与算法的基础知识和经典算法汇总

    目录 算法分析的本质 时间复杂度 概念 计算方法 空间复杂度 概念 认识递归方法 概念 递归的本质 基本的数据结构 线性表 顺序表 链表 栈与队列 栈 队列 重要算法概念 贪心法 分治法 搜索法 宽度优先搜索 分支限界法 总结 算法分析的本质 算法分析就是对时间复杂性和空间复杂性进行分析 时间复杂度 概念 时间复杂性又叫时间复杂度,是对算法运行时间长短的度量. 人们通常只考虑三种情况下的时间复杂性:最坏.最好.平均情况. 计算方法 第一步:声明哪些代码是基本运算 第二步:计算时间复杂度 第三步:

  • C++详细讲解图论的基础与图的储存

    目录 一.前言 二.图的定义 三.图的储存 1.邻接矩阵 2.邻接表 3.邻接矩阵与邻接表的优缺点对比 一.前言 在算法中一般都需要把问题抽象成图论问题然后用图论的算法解决问题. 图论涉及相当多的算法,包括图DFS和BFS.连通性.拓扑排序.最小生成树.最短路径.最大流网络.图的着色问题等等 图论算法在计算机科学中扮演着很重要的角色,它提供了对很多问题都有效的一种简单而系统的建模方式.很多问题都可以转化为图论问题,然后用图论的基本算法加以解决. 二.图的定义 图(graph) 如上图是一个图G,

  • C++零基础精通数据结构之带头双向循环链表

    目录 与单链表的区别 代码的实现 接口 节点的构造 初始化链表 开辟节点 销毁链表 打印链表 尾插链表 尾删链表 头插链表 头删链表 查找链表 链表pos位置的删除 总结 与单链表的区别 单向/双向 单向:只有一个next指针,只指向下一位元素 双向:有两个指针,指向上一位和下一位元素,寻找前一节点和后一节点很便利 带头/不带头 带头:在本来的头结点之前还有一个哨兵卫节点作为头节点,它的址域指针指向头节点,值域不做使用 不带头:没有哨兵卫头节点,在尾删尾插等问题中要考虑头结点的情况(局限) 循环

  • C++入门之模板基础讲解

    目录 前言 引入 模板 函数模板 模板的匹配原则 模板的显示调用 类模板 注意1 注意2 总结 前言 今天博主将要介绍的内容是–模板,他在C++中具有非常重要的位置.至于什么是模板呢?我们请看下面的章节. 引入 我们对交换函数Swap已经非常熟悉了,但是我们经常会遇到这样的一些事,比如,很多不同的数据类型进行交换,那么我们就需要写不同的重载Swap,如下: #include <iostream> using namespace std; void Swap(int& a,int&

  • c/c++基础简单易懂的快速排序算法

    快速排序就是找一个基准,然后其左边要比他小,右边要比他大 int partition(int* a, int left, int right) { int pivot = left;//找最开始位置为基准 int index = left + 1; for (int i = index; i <= right; i++) { if (a[i] < a[pivot]) { swap(a, i, index); index++; } } swap(a, pivot, index - 1);//in

  • C++基础知识之运算符重载详解

    目录 运算符重载 方式一,使用成员函数重载运算符需求:把牛肉换猪肉,羊肉换猪肉 方式二,使用非成员函数[友元函数]重载运算符 两种方式的区别 两种方式的选择: 总结 运算符重载 为什么要使用运算符重载 -C/C++的运算符,支持的数据类型,仅限于基本数据类型. 问题:一头牛+一头马 = ?(牛马神兽?) 一个圆 +一个圆 = ? (想要变成一个更大的圆)一头牛 – 一只羊 = ? (想要变成4只羊,原始的以物易物:1头牛价值5只羊) 解决方案: 使用运算符重载 方式一, 使用成员函数重载运算符

  • C++基础概念讲述

    目录 1.C++相关网站推荐 2.C++和C的关系 3.C++特性说明 3.1与底层硬件紧密结合 3.2对象生命周期的精确控制 3.3Zero-Overhead Abstraction 首先,通过一张最新(2021.11)的编程语言排名图来了解常见的编程语言: 从图中可以看出,C++的排名相对于Python.Java.C来说并不突出,很大的原因是因为C++难度过大,也可以说是知识点太多,我们很难说能精通C++这门语言,只能说对它的部分了解,并能在工作中使用: 1.C++相关网站推荐 1.cppr

  • C++浅析类与对象的基础

    目录 面向过程和面向对象 类的引入 访问限定符 封装 类的作用域 类的实例化 面向过程和面向对象 类和对象是 C++ 的核心特性 我们之前的C语言就属于面向过程,关注过程,分析求解问题的步骤再通过函数调用解决问题:而现在C++是基于面向对象,关注对象,将一个问题拆分成不同对象,依靠对象之间的交互完成. 比如有一个图书馆系统,用C语言面向过程思路就是:统计图书,图书分类,同步上架图书数据,记录借阅信息.而面向对象我们会创建两个类,图书馆和用户,我们关心的是图书馆和用户之间的关系,再分别实现交互,这

  • C++超详细梳理基础知识

    目录 命名空间的使用 来源 命名空间的使用 不展开 部分展开 全展开 函数重载 函数重载的规则 C++如何实现函数重载 引用 命名空间的使用 来源 在了解命名空间的原理和使用之前,我们先要理解,命名空间是为了解决什么问题. C++是在C的基础上发展而形成的一种语言,完全兼容C的语法,也加入了许多新的规则和语法来解决C的缺陷. 命名空间就是为了解决C语言中的重复命名的问题. 首先我们来看看这么一个代码: #include<stdio.h> int main() { int scanf = 20;

  • C语言超详细梳理排序算法的使用

    目录 排序的概念及其运用 排序的概念 排序运用 插入排序 直接插入排序 希尔排序 选择排序 直接选择排序 堆排序 交换排序之冒泡排序 总结 排序的概念及其运用 排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作. 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次 序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排 序算法

  • Java 继承与多态超详细梳理

    目录 一.继承 1.继承的概念 2.继承的语法 3.父类成员访问 (1)子类中访问父类的成员变量 (2)子类中访问父类的成员方法 4.super关键字 5.子类构造方法 6.super和this 7.代码块执行顺序 8.继承方式 9.final关键字 10.继承和组合 二.多态 1.向上转型 2.重写 3.多态 一.继承 1.继承的概念 继承机制:是面向对象程序设计是代码可以复用的最重要手段,允许程序员在保持原有类特性的基础上进行扩展,增加新的功能,产生的新类,成为派生类/子类.继承主要解决的问

  • C++ 超详细梳理继承的概念与使用

    目录 继承的概念及定义 继承的概念 继承定义 定义格式 继承关系和访问限定符 继承基类成员访问方式的变化 基类和派生类对象赋值转换 继承中的作用域 派生类的默认成员函数 继承与友元 继承与静态成员 复杂的菱形继承及菱形虚拟继承 菱形继承 虚拟继承解决数据冗余和二义性的原理 继承的总结和反思 继承的概念及定义 继承的概念 继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类.继承呈现了面向对象程序设计的层次结构,体

  • python 字典常用方法超详细梳理总结

    目录 1.字典的概念 2.字典的主要特征 3.创建字典的三种方法 4.字典常用方法 1.clear() 2.copy() 3.get() 4.keys() 5.values() 6.items() 7.del() 8.zip() 1.字典的概念 字典和列表类似,也是可变序列,不过和列表不同,它是无序的可变序列,保存的内容是以键值对(key:value)形式存放的 字典的每个键值之间用冒号:分隔,每个键值对之间用,隔开,整个字典包含在{ }中 dict = {key1:value1,key2:va

  • Python 常用内置模块超详细梳理总结

    目录 time模块 time.sleep() time.time() time.localtime() time.strftime() datetime() random模块 random.random() random.randint() random.choice() random.shuffie() random.randrange() random.sample() json模块 json.loads() json.dumps() json.load() json.dump() OS模块

  • python 列表常用方法超详细梳理总结

    目录 列表是什么? 列表常用方法 1.append() 2.clear() 3.copy() 4.count() 5.extend() 6.index() 7.insert() 8.reverse() 9.remove() 10.pop() 11.sort() 列表是什么? 列表由一系列特定顺序排列的元素组成,你可以创建包含字母表中的所有字母.数字0~9.所有家庭成员姓名的列表等等,也可以将任何东西放入列表中,其中元素之间可以没有任何关系,鉴于列表通常包含多个元素,给列表指定一个表示复数的名称(

  • C语言自定义类型超详细梳理之结构体 枚举 联合体

    目录 一.什么是结构体 1.结构体实现 2.匿名结构体类型 3.结构体自引用 4.结构体的内存对齐 5.结构体位段  二.什么是枚举 1.枚举类型的定义 2.枚举的优点 三.联合(共用体) 1.什么是联合(共用体) 2.联合(共用体)的定义 3.联合(共用体)的初始化 总结 一.什么是结构体 结构是一些值的集合,这些值称为成员变量.结构的每个成员可以是不同类型的变量. //结构体声明 struct tag //struct:结构体关键字,tag:标签名,合起来是结构体类型(类型名) { memb

  • C语言 语义陷阱超详细梳理总结

    目录 1 指针与数组 2 非数组的指针 3 作为参数的数组声明 4 空指针并非空字符串 5 边界计算与不对称边界 6 求值顺序 7 整数溢出 8 为函数提供返回值 1 指针与数组 C语言中只有一维数组.数组中的元素可以是任意类型的对象,这也是多维数组构建的理论基础所在 对于一个数组,我们只能做两件事:确定该数组的大小以及获得该数组下标为0的元素的指针.任何一个数组下标运算都等同于一个对应的指针运算. 数组名代表首元素的地址,无法对其进行++或者–操作,换句话说,我们无法改变数组名(表示的值),因

  • C语言 超详细梳理总结动态内存管理

    目录 一.为什么存在动态内存分配 二.动态内存函数的介绍 1.malloc和free 2.calloc 3.realloc 三.常见的动态内存错误 1.对NULL指针的解引用操作 2.对动态开辟空间的越界访问 3.对非动态开辟的空间使用free释放 4.使用free释放一块动态开辟空间的一部分 5.对同一块开辟的空间多次释放 6.动态内存开辟忘记释放(内存泄漏) 四.几个经典的笔试题 一.为什么存在动态内存分配 我们已经掌握的内存开辟方式有: int a = 10://在栈空间开辟4个字节的连续

随机推荐