【C++】C++初阶入门(一)

一、C++的源起始末

       在谈C++之前,C语言是一个无论如何都不能绕开的话题。C语言是大家在初次接触编程时最常见的语言,而且使用最为普遍。然而在我们学习的后期,随着我们遇到的问题的复杂度上升,C语言的局限和短板已经不利于我们去解决规模较大的问题了

       因此,在20世纪80年代,通过对C语言进行补强,一种全新的语言C++出现了。C++不但兼容C语言,可以进行C语言条件下的程序编写,而且既可以以抽象数据为特点进行基于对象的程序设计,又能够进行面向对象程序设计,在很大程度上补齐了C语言只能解决小规模问题的短板。

       那么接下来,就随笔者一起学习这门复杂难精但趣味横生的语言吧!

二、推开C++的大门

(一)命名空间

       在C语言中,我们知道有很多变量和函数是在内部早就定义好的,存在于一定的作用范围。因此有一个比较常见的错误就是在程序中出现变量存在命名冲突。如下代码所示:

#include <stdio.h>
#include <stdlib.h>

int rand = 10;

int main()
{
	printf("%d\n", rand);
	return 0;
}

       这是一个简单C语言程序,但是一运行就必定报错。因为在stdlib.h的头文件中包含了rand()函数,这就造成了编译报错。

       我们都知道,在C语言以及C++中,存在着大量以上情况的变量、函数以及之后会学到的类。它们都普遍存在于全局作用域中,而且一个差错就会导致编译不通过。在C语言的框架下无法解决这样的问题,于是C++就提出了命名空间来处理,来避免命名冲突或名字污染

       在C++中设计了namespace关键字,用于命名空间的定义。命名空间的定义也十分简单,只需要在namespace后面跟命名空间的名字,再接上{}即可,{}中就是该命名空间的成员。

namespace ywd       //命名空间+名字
{
	int rand = 10;  //命名空间的成员
}

       这样就解决了命名冲突的问题了。既然命名空间定义结束,接下来就需要探讨命名空间的用法了。

命名空间的三种用法
1.使用作用域限定符

       如果命名空间定义结束后直接运行如下代码,结果依旧是报错:

#include <stdio.h>

namespace ywd
{
	int a = 10;
}

int main()
{
	printf("%d\n", a);
	return 0;
}

       既然已经定义了一个命名空间,我们想使用该命名空间的成员,就需要用到作用域限定符 :: 来调用命名空间内的成员。

#include <stdio.h>

namespace ywd
{
	int a = 10;
}

int main()
{
	printf("%d\n", ywd::a);  //命名空间名 + :: +空间成员名
	return 0;
}
2.使用using展开命名空间成员

       如果该命名空间中的某一成员调动频繁,我们可以使用using来展开该成员,使其作用于全局域中,不必使用作用域限定符。

#include <stdio.h>

namespace ywd
{
	int a = 10;
    int b = 1;
}

using ywd::a;               //使用using展开成员a

int main()
{
	printf("%d\n", a);      //无需作用域限定符就可以调用a
    printf("%d\n", ywd::b); //成员b没有被展开
	return 0;
}
3.使用using展开整个命名空间

       using除了可以展开命名空间内的某个成员,也可以将整个命名空间展开。一般在做大型项目时不建议展开整个命名空间(不论是自己定义的命名空间还是标准命名空间),容易导致空间内成员与其它变量等产生命名冲突或名字污染,所以很少会使用第三种方法。

#include <stdio.h>

namespace ywd
{
	int a = 10;
    int b = 1;
}

using namespace ywd;     //using + namespace + 命名空间名

int main()
{
	printf("%d\n", a);   //可以直接调用空间内成员
    printf("%d\n", b);
	return 0;
}
(二)输入和输出

C++虽然脱胎于C语言,但在一些基础语法上也大相径庭。其中最为典型的例子就是输入和输出语句。C语言中我们主要使用printf语句和scanf语句进行输入输出,而C++的输入输出语句如下代码所示:

#include <iostream>
//std:C++标准库的命名空间
using namespace std;

int main()
{
	// << 流插入运算符
	cout << "hello,world!"<<endl;  //endl表示换行输出
	int i = 0;
	// >> 流提取运算符
	cin >> i;
	//cin和cout可以自动识别类型
	return 0;
}

C++使用cout标准输出对象(控制台)cin标准输入对象(键盘),且必须在使用时包含头文件<iostream>和使用标准命名空间。从代码中明显看出,C++的输入输出方式较C语言更为方便,不必手动控制格式。

(三)缺省参数

缺省参数是在定义或声明时为函数的参数提供一个缺省值,在调用该函数时,如果没有指定的实参,就采用形参的缺省值,否则就使用指定实参。比如在C语言程序中,我们初始化一个栈时,并不知道需要开辟多少空间才不会造成短缺或浪费。如果在C++程序中,我们可以指定一个缺省值,在初始化时就不必考虑空间的大小问题,后续也可以对其进行修改,并且C语言程序不可以使用缺省值

#include <iostream>
using namespace std;

//缺省参数
void func(int a = 10)
{
	cout << "a = " << a << endl << endl;
}

int main()
{
	func();         //没有传入实参时,使用形参的缺省值
	func(1);        //有传入实参时,使用指定的实参

	return 0;
}
缺省参数的两种类
1.全缺省参数

顾名思义,即函数的所有形参都有缺省值。

//全缺省参数
void func(int a = 10, int b = 20, int c = 30)
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}

int main()
{
	func(1, 2);        //a = 1, b = 2, c = 30
	func(1, 2, 3);     //a = 1, b = 2, c = 3
	
	return 0;
}
2.半缺省参数

不用顾名思义,指的是函数只有部分形参有缺省值。

//半缺省参数
void func(int a, int b = 20, int c = 30)    //只要a没有缺省值
{
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl << endl;
}

int main()
{

	func(1, 2);     //a = 1, b = 2, c = 30
	func(1, 2, 3);  //a = 1, b = 2, c = 3
	
	return 0;
}
关于缺省参数的注意事项:

● 半缺省值必须从右往左依次赋予,且不能出现间隔

//错误示例
int func(int a = 10, int b = 20, int c)  //不能从左往右,只能从右往左

int func(int a = 10, int b, int c = 30)  //不能出现间隔,必须依次赋值

● 缺省值不能在函数声明和定义中同时出现。

  缺省值如果同时出现在声明和定义中,且提供的缺省值各不同,则编译器无法确定使用哪一个缺    省值。

● 缺省值必须是常量或全局变量

(四)函数重载

函数重载是函数的一种特殊情况,C++允许在同一作用域中声明数个功能相似的同名函数。这些函数通常形参列表不同,大多数是为了处理功能相近但数据类型不同的情况。一般根据形参列表的不同又可以分为三类。

函数重载的三种类
1.参数类型不同
#include <iostream>
using namespace std;

//1.参数类型不同
int Add(int left, int right)
{
	cout << "int Add(int left, int right)" << endl;
	return left + right;
}

double Add(double left, double right)
{
	cout << "double Add(double left, double right)" << endl;
	return left + right;
}

int main()
{
	Add(1, 2);
	Add(1.1, 2.1);

	return 0;
}

2.参数个数不同 
#include <iostream>
using namespace std;

//2.参数个数不同
void Func()
{
	cout << "Func()" << endl;
}

void Func(int a)
{
	cout << "Func(int a)" << endl;
}

int main()
{
	Func();
	Func(1);

	return 0;
}

3.参数类型顺序不同 
#include <iostream>
using namespace std;

//3.参数类型顺序不同
void Two(int a, char b)
{
	cout << "void Two(int a, char b)" << endl;
}

void Two(char b, int a)
{
	cout << "void Two(char b, int a)" << endl;
}

int main()
{
	Two(1, 'a');
	Two('a', 1);

	return 0;
}

 C++支持函数重载的原因

和C语言相比,C++的函数重载是相当便捷的。那为什么C语言不支持函数重载,C++却支持呢?这就涉及C/C++程序运行的过程。

在C/C++中,运行一个程序需要经过预处理、编译、汇编和链接这四个阶段。我们的源文件在汇编过程中会分别处理出主函数和函数的符号表。在链接阶段会合并符号表。在C语言中,如果函数出现重复定义的话,在编译过程中就会出现重定义报错。因为C语言程序编译时,不会对函数名进行修饰,如果出现重名就会引发歧义,导致函数调用出错。而在C++中,程序在编译时会按照特定的函数修饰规则对函数名进行修饰,两个功能不同的函数即使函数名相同,但修饰之后就可以对二者做出区分。

 三、结语

以上就是本文的全部内容,但这只是C++入门的部分知识,在之后笔者会进行后续介绍和讲解,和大家一起继续深入学习与探讨C++的无穷奥妙。感谢观看!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值