您的位置:首页 > 编程语言 > C语言/C++

C++基础入门知识

2017-06-19 16:07 183 查看
1.命名空间

我们在一开始接触C++时,会发现与C语言除了一开始引用的头文件不同,还有就是using namespce std;这句话。不清楚到底做了些什么事情。其实:这就是C++中的命名空间。因为标准库非常的庞大,程序员在选择的类的名称或函数名时就很有可能和标准库中的某个名字相同。所以为了避免这种情况所造成的名字冲突,就把标准库中的一切都被放在名字空间std中。接下来正式的了解一下命名空间的作用以及用法。

<1>概念:


命名空间是为了防止名字冲突提供更加可控的机制。命名空间分割了全局命名空间,其中每一个命名空间是一个作用域。由三部分组成,分别是namespace、空间名字和一系列由花括号括起来的声明和定义。

<2>例子:

①如果我们每次在程序一开始不写unsing namespace std; 那么C++中对应的一些标识符信息我们就找不到,在每次使用时都得像如下写,显然这样十分麻烦。

注:endl如同C语言中的\n


	int a = 10;
std::cout <<a << std::endl ;
②如何输出一个在全局域中的值(假设我们先在外部定义了一个全局变量 int a = 10;)?
cout <<::a << endl
如果我们在a前面不加其他符号则说明是输出就近的值,加上::表明输出::前作用域对应的值,::是作用域解析符由于此时::前面没有名字,则默认代表为全局变量。

③如何自己定义一个命名空间并输出对应的值?
#include <iostream>
#include <Windows.h>
using namespace std;

namespace a1
{
int a = 20;
}

int main()
{
int a = 10;
cout <<a1::a << endl;
system("pause");
return 0;
}
虽然我们在main函数内部定义了一个a=10,但是在我们输出的时候确实从a1这个命名空间中取对应的值,所以输出20。
④命名空间嵌套怎么使用?

#include <iostream>
#include <Windows.h>
using namespace std;

namespace a1
{
int a =
4000
20;
namespace a2
{
int a = 30;
}
}

int main()
{
int a = 10;
cout <<a1::a2::a << endl;
system("pause");
return 0;
}
只需要在cout输出时按照嵌套的顺序找到对应的域,并输出即可。
小结:在上述问题中还包括一个知识点,我们定义了许多个a,但是由于他们都处于不同的域,所以运行时并不会报错。




2.C和C++输入输出简单对比

C中的输出输出以及各种转义字符应该都很熟悉,但是在C++中,cout是标准输出流对象,<<是输出操作符;cin是标准输入流对象,>>是输入操作符。

先简单介绍下二者怎么使用:

cout语句的一般格式为:

    cout<<表达式1<<表达式2<<……<<表达式n;

cin语句的一般格式为:

    cin>>变量1>>变量2>>……>>变量n


#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <Windows.h>
using namespace std;

int main()
{
int a = 0;
double b = 0.0;

printf("//////C写法////////\n");
scanf("%d", &a);
scanf("%lf", &b);
printf("C: int a = %d\n", a);
printf("C: double b = %lf\n", b);

cout<<"//////C++写法///////"<<endl;
cin >> a;
cin >> b;
cout << "C++: int a = " << a << endl;
cout << "C++: double b = " << b << endl;

system("pause");
return 0;
}
输出结果:


















在用cout输出时,用户不必通知计算机按何种类型输出,系统会自动判别输出数据的类型,使输出的数据按相应的类型输出。

在用cin输入时,系统也会根据变量的类型从输入流中提取相应长度的字节

但是假如你想在C++实现类似于C中格式控制那样的功能,就得用到输入输出流的控制符。







简单举两个例子:

①以十六进制输出:


	int a = 10;
cout << hex << a << endl;
②输出正数时给出‘+’号(输出+10):
	int a = 10;
cout << setiosflags(ios::showpos) << a << endl;

需要注意的是: 如果使用了控制符,在程序单位的开头除了要加iostream头文件外,还要加iomanip头文件。



3.重载(C++为什么支持重载?)

<1>重载规则:

① 函数名要相同;

② 参数个数不同,参数类型不同,参数顺序不同,均可构成重载;

③ 返回值类型不同则不可以构成重载。

<2>原理:

在C++中,利用name mangling(倾轧)技术来实现重载,通过命名倾轧来改名函数名,区分参数不同的同名函数。正因为这个倾轧技术需要根据参数的顺序和类型,所以参数的顺序和类型不同都可以构成重载。

例如下面几个函数,我们在真正用函数名时其实利用的是类似于后面注释内容形式的名字,其中_Z是默认前缀,3表示函数名的字符个数,fun为函数名,后面的字母是参数类型的首字母。所以我们可以发现函数返回值类型并没有涉及到命名当中,只要满足重载的规则,其实就可以实现函数的重载实现。


void fun(int a);		//_Z3funi
void fun(char a);		//_Z3func
void fun(int a, char b);       //_Z3funic
void fun(char a, int b);       //_Z3funci

4.C++缺省参数

<1>概念:


  在函数声明或定义的时候给形参一个默认的参数。这样在调用该函数,如果没有给实参,函数的这个形参就默认为这个值。


<2>使用规则:

①缺省值必须从右往左给定值,且必须连续,不能两个给定值中间加有未赋值(若缺省参数a,b全部赋值则为全缺省,若只有一个赋值则为半缺省)。

#include <iostream>
#include <Windows.h>
using namespace std;

int fun(int a, int b=10)
{
return a + b;
}

int main()
{
int ret = fun(1);
cout << ret << endl;
system("pause");
return 0;
}
由于实参只给定了一个,所以形参中a=1,而b使用缺省参数值10,返回值为11。
切记不可将缺省参数写为类似如下样子,缺省参数赋值必须要连续且从右向左赋值:


int fun(int a=10, int b,int c= 10)
②缺省值必须为常量或全局变量;
③缺省值只能出现在声明或定义的其中一处;


④不能把const的全局变量作为缺省值;


⑤缺省值并不构成函数重载;




5.指针和引用

简单地说:C语言中想要间接修改一个变量的值,就需要引入指针。创建一个指针指向需要修改的元素,指针内部存放的是指向变量的地址。而C++中就需要使用引用。给需要修改的元素起一个“别名”,然后再修改。






<1>定义格式:

类型& 引用变量名  =   已定义过的变量名;


	int a = 10;
int& b = a; //给a变量起一个别名b
b = 20;
cout << b << endl;
<2>需要注意的地方:
① 一个可以取多个别名;


② 引用必须初始化;

③ 引用只能在初始化的时候引用一次,不能改变再引用其他的变量。


<3>使用方法:

一、const引用


	int d1 = 4;
const int& d2 = d1;
d1 = 5;           //d1 修改, d2值也改变
//d2 = 6;         //由于d2是const修饰的引用,具有常属性,不能修改

const int d3 = 1;
const int& d4 = d3; //d3是const修饰的引用,所以d4引用也必须是const修饰

double d5 = 1.2;
//int& d6 = d5;     //错误原因见图解
const int& d7 = d5;




想要用int类型的d7来引用double型的d5,首先先会将d5变量放入一个int类型临时变量,再用const int类型的d7来引用这个临时变量,临时变量具有常属性,所有就需要有一个const int类型的名字来完成这个引用。


二、引用作为参数

①如果形参为引用类型,则形参是实参的别名。(可以与实参同名)


void swap(int& num1, int& num2)
{
int tmp = num1;
num1 = num2;
num2 = tmp;
}

②当不希望函数内部改变参数值时,尽量使用常引用传参。例如:

int Add(const int& num1, const int& num2);
三、传引用作为返回值

例一:

int& Add(const int& num1, const int& num2)
{
int ret = num1 + num2;
return ret;
}

int main()
{
int num1 = 10;
int num2 = 20;
const int& c = Add(num1, num2);
cout << c << endl;

system("pause");
return 0;
}
输出结果是30,没有任何问题。但是!再稍微改下我们就会发现问题!

例二:

void fun(int num1, int num2)
{
int res = 0;
res = num1 + num2;
}

int& Add(int num1, int num2)
{
int ret = 0;
ret = num1 + num2;
return ret;
}

int main()
{
int num1 = 10;
int num2 = 20;
const int& c = Add(num1, num2);
cout << c << endl;

fun(5, 6);
cout << c << endl;

system("pause");
return 0;
}
结果:


只是将例一的Add函数的返回值变成了返回值的引用,结果就变了!接下来就介绍下为什么!

Add函数在返回ret时会由编译器创建一个临时变量,而我们返回的是这个临时变量的引用,第一次输出时也就会对应输出这个临时变量引用的值;在第二次输出c时,我们进入fun函数在赋值过程中,再次用到了之前位置 的临时变量,但是现在这个临时变量已经不是之前的那个,编译器也就会给我们返回一个随机值。


小结:①:不要返回一个临时变量的引用;

           ②:如果返回对象除了当前函数的作用域依旧存在,则最好使用引用返回。


<4>引用和指针的区别

①引用只能在定义时初始化一次,之后不能再指向其他变量;指针变量可以;

②引用必须指向有效的变量,指针可以指向为NULL;

③sizeof引用得到的是所指向的变量的大小,而sizeof指针是对象地址的大小;

④指针和引用自增和自减意义不同;

⑤相对而言,引用比指针更安全。




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: