【C++】C++入门——(上)

前言:结束了上一阶段的数据结构的学习,就逐步的步入到C++的学习了。C++是一个更高级的语言,这也意味着它相比C语言有更多的优势也会更加便捷;但是难度相较于C语言也比较大。小编希望与大家共同学习将c++学到一个不错的水平,加油!

文章目录

一,C++介绍

C++ 是一种通用编程语言,由 Bjarne Stroustrup 于 1985 年在贝尔实验室开发。它是对 C 语言的扩展,引入了面向对象编程(OOP)特性,同时保留了对底层硬件的直接操作能力。

C++的核心特性:

  1. 面向对象:支持类、继承、多态和封装。
  2. 高性能:允许直接内存操作,适合系统级开发。
  3. 泛型编程:通过模板实现代码复用。
  4. 标准库:提供丰富的容器、算法和输入输出功能。

以上就是C++的介绍,要想学好一门语言就要先从其语法开始学习,下面就来介绍一下C++的语法。

二,C++语法

回忆一下在学C语言的时候第一个程序是怎样写的?

c 复制代码
#include<stdio.h>
int main()
{
	printf("hello world!\n");
	return 0;
}

相信大部分人在初学C语言的时候就写过这样的代码。那么这段程序如果换成C++应该怎么写呢?

这里有人会有疑问说C++是高级语言可以兼容C这个写法在C++中也能编译通过。

这样的做法的确可以,但是C++拥有一套自己的输入输出,下面我们来看代码:

cpp 复制代码
#include<iostream>
using namespace std;
int main()
{
	cout<<"hello world!\n"<<endl;
	return 0;
}

以上就是C++写hello world的写法,一眼望去C++与C的代码行数有些不同,C++比C多了一行using namespace std;。到这可能会有人问,这一行代码代表什么?有什么含义?这就是小编接下来要讲的语法点命名空间。

2.1命名空间

什么是命名空间?命名空间用来解决什么问题?下面我们用一个例子来引入

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

int rand = 10;
int main()
{
	// 编译报错:error C2365: "rand": 重定义;以前的定义是"函数"
	printf("%d\n", rand);
	return 0;
}

上面这个例子我们看到编译器报了rand重定义的错误,要了解为什么会报重定义我们还需要看下面这个例子:

cpp 复制代码
#include<stdio.h>
int x = 10;
int main()
{
	int x = 20;
	printf("%d", x);
	return 0;
}

先来看看上面这段程序输出是什么?当然有了前面C语言的基础这里一看就是输出的是20。那为什么我们能判断是20而不是10呢?这其实就是这两个x的作用域不同,一个在全局域(静态区),一个在局部域(函数栈帧)这就足以将它们区分开。

如果将外面的x拿进去,会发生什么?

c 复制代码
#include<stdio.h>
int main()
{
	int x = 10;
	int x = 20;
	printf("%d", x);
	return 0;
}

这时候编译运行就会发现报了一个重定义的错误:

这次的错误就与上面我们引出的例子报的错误相似了,我们不妨再变一下:

c 复制代码
#include<stdio.h>
int add(int x,int y)
{
	return x+y;
}
int add=10;
int main()
{
	int x = 20;
	printf("%d", x);
	return 0;
}

看到这是不是就和上面那个例子报的错误一样了,那我们只要分析这段代码的问题就可以知道上面代码的问题了。我们先来看错误说重定义,以前定义的是函数,这个很好理解说白了就是它们的名称冲突了,都在全局域名称又一样所以编译器碰到add时分不清是哪个,上面rand重定义也是一个道理,它是与头文件中定义的rand冲突了。

那么如果想要定义同名变量或函数怎么办呢?

答案就是使用命名空间将他们隔离。所以我们看到命名空间解决的就是在同一个域的命名冲突的问题。

2.2namespace的定义

  • 定义命名空间,需要使⽤到namespace关键字,后⾯跟命名空间的名字,然后接⼀对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。

还是上面的例子如果想让它们不冲突,就可以使用命名空间:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
//命名空间里可以定义 变量 函数 结构体
namespace slu
{
	int rand = 10;

	int Add(int x, int y)
	{
		return x + y;
	}

	struct Node
	{
		struct Node* next;
		int val;
	};
}
int Add=10;
int x=10;
int main()
{
	int x = 1;
	//printf("%d\n", y);
	//不指定域 在寻找x的时候就先局部后全局
	printf("%d\n", x);
	//如果想访问外部的这个x就加上 :: 域作用限定符指定全局域
	printf("%d\n",::x);
	printf("%p\n", rand);
	//指定访问slu这个命名空间里的rand
	printf("%d\n", slu::rand);
	return 0;
}
  • 从上面的代码可以看到namespace本质是定义出⼀个域,这个域跟全局域和局部域各自独立,不同的域可以定义同名变量,所以下面的rand不在冲突了。

  • 注意C++中的域有局部域,全局域,类域,命名空间域,域主要影响的就是编译器在编译时查找语法出处的一个逻辑。所以同名变量在不同的区域,同名的冲突就得到了解决,就像一个班级里面如果有同名的学生老师也会分不清哪个是哪个,如果是不同班级的同名学生由于班级不同就能够区别开来。

  • 局部域和全局域除了会影响编译查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量sheng命周期。

  • 两个同名的命名空间可以合并看作是一个,不会冲突。

  • 命名空间还支持嵌套定义比如:

cpp 复制代码
namespace stack
{
	namespace A
	{
		void Add(int x,inty)
		{
			return x+y;
		}
	}
	namespace B
	{
		void Add(int* x,int* y)
		{
			int tmp=*x;
			*x=*y;
			*x=tmp;
		}
	}
}

假如有个命名空间的名称为stack 有一个程序A对stack这个命名空间里的内容进行修改,同时又有一个程序员B也修改的是同一个地方 那么为了区分它们的内容就用命名空间分开。由于它们修改的是stack所以嵌套在stack这个命名空间里面。

2.3命名空间的使用

命名空间的三种使用方法:

  1. 指定命名空间访问
cpp 复制代码
namespace A
{
	int a=10;
	int b=20;
}
int main()
{
	//printf("%d",b);会编译报错,局部域全局域都找不到A
	printf("%d",A::b);
	return 0;
}
  1. 将命名空间中的某个成员展开
cpp 复制代码
namespace A
{
	int a = 10;
	int b = 20;
}

using A::b;
int main()
{
	
	printf("%d\n", A::b);
	//展开了b就相当于把b放在了全局域上
	printf("%d\n", b);
	return 0;
}
  1. 将命名空间全部展开,冲突风险很大。
cpp 复制代码
namespace A
{
	int a = 10;
	int b = 20;
}

using namespace A;
int main()
{
	//全部展开 那么命名空间里的成员就都不用指定了。
	printf("%d\n", A::b);
	printf("%d\n", b);
	printf("%d\n",A:a);
	printf("%d\n",a);
	return 0;
}

三,C++输入和输出

还是上面那段代码:

cpp 复制代码
#include<iostream>
using namespace std;
int main()
{
	cout<<"hello world!\n"<<endl;
	return 0;
}

我们已经解释了命名空间了,接下来就剩头文件和main函数里的代码了。

  1. 首先看头文件<iostream>这时Input Output Stream 的缩写,它是标准的输入输出流库,定义了标准的输入输出流对象。
  2. std::cout是ostream类的对象它主要⾯向窄字符的标准输出流。
  3. std::cinistream类的对象它主要面向窄字符的标准输入输出流。
  4. <<>>在C语言中是移位运算符,但在C++中<<是流插入,>>是流提取。endl是endline的简写它是一个函数,流插入输出时,相当于插入一个换行字符加刷新缓冲区。
  5. cout/cin/endl都包含在C++标准库中,而C++标准库又包含在一个叫std(standard)的命名空间中,因此要使用就要展开或指定展开命名空间。
  6. C++这套输入输出相比C语言优势在于不用管类型了;printf 指定格式 语法原生定义类型即内置类型像(int double char),不支持类类型,而cout与cin它会自动识别类型,而且也支持自定义类型,可以说它的本质就是为了支持任意类型输出输入。关于类的问题将会在类和对象章节介绍。
cpp 复制代码
#include<iostream>
using namespace std;
int main()
{
	int a=10;
	double b=20;
	char c="x";
	std::cout<<a<<" "<<b<<" "<<c<<" "<<std::endl;
	//展开了命名空间就不用指定命名空间了
	cout<<a<<" "<<b<<" "<<c<<" "<<endl;
	scanf("%d %lf", &a, &b);
	printf("%d %lf\n", a, b);
	
	cin >> a;
	cin >> b >> c;
	cout << a << endl;
	cout << b << " " << c << endl;
	return 0;
}

四,缺省参数

  1. 缺省参数就是在函数声明或定义的时候为函数的参数指定的一个缺省值,在调用函数时如果没有传对应参数的实参,那么就默认使用缺省值;如果传了对应的实参那么就使用指定传过来的那个参数。
cpp 复制代码
#include<iostream>
using namespace std;
void func(int x=10)
{
	cout<<x<<endl;
}
int main()
{
	func();//没有指定传的实参 就使用缺省值此时x为10
	func(1);//指定传了实参 就使用传过去的实参 此时x为1
	return 0;
}
  1. 缺省值还分全缺省和半缺省,这应用在函数有多个参数的场景。缺省值就是函数的参数都给了特定的值(缺省值),半缺省就是部分函数的参数给了特定的值。
cpp 复制代码
#include<iostream>
using namespace std;
//全缺省
void func1(int a=1,int b=2,int c=3)
{
	cout<<"a="<<a<<" "<<endl;
	cout<<"b="<<b<<" "<<endl;
	cout<<"c="<<c<<" "<<endl; 
}
//半缺省
void func2(int a,int b,int c=3)
{
	cout<<"a="<<a<<" "<<endl;
	cout<<"b="<<b<<" "<<endl;
	cout<<"c="<<c<<" "<<endl; 
}
int main()
{
	func1();//abc都不传有缺省值1,2,3
	func1(10,20);//只传ab c有缺省值10 20 3
	func1(10,20,30);//都传abc 10 20 30
	
	//c传实参有缺省值3
	func2(10,20);
	//c传实参有缺省值100
	func2(10,20,100);
	
}

注意半缺省在给缺省值的时候要从右到左依次给缺省值,在调用函数传值的时候要从左往右依次传值,不能跨越传值,也不能跨越的给缺省值!

  1. 当函数的声明和定义分离时,缺省参数不能在声明和定义中同时出现,规定必须在函数的声明那里给缺省值,也就是只能给在头文件中的函数函数声明加缺省值。
    举个例子:

在头文件中定义一个栈:

cpp 复制代码
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
//在这里给上缺省值
void STInit(ST* ps, int n = 4);

在.cpp文件中

cpp 复制代码
void STInit(ST* ps, int n)
{
assert(ps && n > 0);
ps->a = (STDataType*)malloc(n * sizeof(STDataType));
ps->top = 0;
ps->capacity = n;
}

这里其实也体现了,缺省参数的应用,当我们不知道要开多大的空间那么在使用STInit这个函数的时候就不传第二个参数,让他默认使用缺省值,当我们指定传值过去的时候它就会根据我们的值开空间,这样使用起来非常的方便。

以上就是本章的全部内容啦!

最后感谢能够看到这里的读者,如果我的文章能够帮到你那我甚是荣幸,文章有任何问题都欢迎指出!制作不易还望给一个免费的三连,你们的支持就是我最大的动力!

相关推荐
橙序员小站2 分钟前
Lombok vs Java Record:谁才是未来?
java·开发语言·python
空白到白2 分钟前
Python-机器学习概述
开发语言·python·机器学习
小苏兮12 分钟前
【C++】类与对象(上)
开发语言·c++·学习
Zhu_S W17 分钟前
JFreeChart全面指南:在Java中创建数据可视化图表
java·开发语言·信息可视化
大龄门外汉22 分钟前
CPP学习之map和set
c++·笔记·学习·stl·set·map·改行学it
上官鹿离33 分钟前
C++学习笔记之输入输出流
c++·笔记·学习
仰泳之鹅44 分钟前
【C语言】深入理解指针(2)
c语言·开发语言
Want5951 小时前
Python Android Studio Logo
开发语言·python·android studio
草莓熊Lotso1 小时前
【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day15
c语言·开发语言·经验分享·强化
小乖兽技术2 小时前
C#与C++交互开发系列(三十):C#非托管内存分配大比拼,哪种方式才是真正的性能王者?
c++·c#·交互