第一章 C++基础 —— 概述

C++基础 —— 概述


第一章 C++概述、简单知识点介绍

C语言和C++的联系

C++ 和C语言虽然是两门独立的语言,但是它们却有着扯也扯不清的关系。早期并没有“C++”这个名
字,而是叫做“带类的C”。“带类的C”是作为C语言的一个扩展和补充出现的,它增加了很多新的语法,目 的是提高开发效率。
这个时期的 C++ 非常粗糙,仅支持简单的面向对象编程,也没有自己的编译器,而是通过一个预处理程序(名字叫 cfront),先将 C++ 代码”翻译“为C语言代码,再通过C语言编译器合成最终的程序。随着 C++ 的流行,它的语法也越来越强大,已经能够很完善的支持面向过程编程、面向对象编程
(OOP)和泛型编程,几乎成了一门独立的语言,拥有了自己的编译方式。
C++ 拥有独立的编译器,例如 Windows 下的微软编译器(MSVC)、Linux 下的 GCC 编译器、Mac 下的 Clang 编译器,它们都同时支持C语言和 C++,统称为 C/C++ 编译器。对于C语言代码,它们按照C语言的方式来编译;对于 C++ 代码,就按照 C++ 的方式编译。
从表面上看,C、C++ 代码使用同一个编译器来编译,所以上面我们说“后期的 C++ 拥有了自己的编译方式”,而没有说“C++ 拥有了独立的编译器”。
从语法上看,C语言是 C++ 的一部分,C语言代码几乎不用修改就能够以 C++ 的方式编译。

  1. 从语法上来讲,C语言是C++的一部分,C语言代码几乎不用修改就能够用C++的方式编译。细致来讲,C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现过程(事务)控制)。
  2. C++,首要考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事务)控制。 所以C与C++的最大区别在于它们的用于解决问题的思想方法不一样。之所以说C++比C更先进,是因为“ 设计这个概念已经被融入到C++之中 ”。

头文件

C++为了兼容C,支持所有的C头文件,但为了符合C++标准,所有的C头文件都有一个C++版本的,
即去掉.h,并在名子前面加c。如和。

|C语言| C++|
|stdio.h |iostream|
|math.h |cmath|
|string.h |cstring|
|stdlib.h |cstdlib|

命名空间namespace

namespace是指标识符的各种可见范围。名称(name)可以是符号常量、变量、函数、结构、枚举、类和对象等等。工程越大,名称互相冲突性的可能性越大。
假设这样一种情况,当一个班上有两个名叫 maye的学生时,为了明确区分它们,我们在使用名字之外,不得不使用一些额外的信息,比如他们的家庭住址,或者他们父母的名字等等。为了解决上输入问题,引入了命名空间这个概念,它可作为附加信息来区分不同库中相同名称 的函数、类、变量等。本质上,命名空间就是定义了一个范围。

注意:命名空间只能在全局内定义。
命名空间别名参照下面实例,using声明可以使得指定的标识符可用。

#include<iostream>
using namespace std;
//命名空间只能放在全局、也可以实现实现和定义分离
namespace A {
	int a = 10;
	// 命名空间可以嵌套命名空间
	namespace B {
		int a = 20;
	}
	void coutHello() {
		cout << "hello"<<endl;
	}
	/*
		coutHi不可用 如果命名空间包含一组重载的函数;
		using声明就声明了这个重载函数的所有集合
	 */
	void coutHello() {
		cout << "hello" << endl;
	}
	
	void coutHi() {
		cout << "hi"<<endl;
	}
}
namespace B {
	int a = 100;
}

int main(){
	cout << "A::a : " << A::a << endl;
	cout << "A::B::a : " << A::B::a << endl;

	namespace  otherName = A;
	cout << "otherName of A ::a :" << otherName::a << endl;
	
	using A::coutHello;
	coutHello();

}

using遇到重载函数时,声明了这个重载函数的所有集合。

#include<iostream>
using namespace std;

namespace A {
	void func() {}
	void func(int x) {}
	int  func(int x, int y) { return 1; }
}
int main() {
	using A::func;
	func();
	func(10);
	func(10, 20);
	return 0;
}

输入输出

C语言的的输入输出用的主要是scanf()、printf()函数,而C++是使用类对象cin、cout进行输入输
出。
cin 输入流对象
cout 输出流对象
endl 换行,并清空输出缓冲区(end line 结束一行,并另起一行)
\n照样可以在cout中使用

基本数据类型

C++和C的基本数据类型几乎一样
值得注意的是,C语言中虽然也有bool(布尔类型),但是需要包含头文件<stdbool.h>,而在C++中则 不用,直接使用即可。
布尔类型对象可以被赋予文字值true或false,所对应的关系就是真与假的概念,即1,0。 可以使用boolalpha打印出bool类型的true或false

结构体加强

c中定义结构体变量需要加上struct关键字,然而c++不需要。c++既可以定义成员变量,也已定义成员函数。然而c能定义成员函数。

//1. 结构体中即可以定义成员变量,也可以定义成员函数
struct Student{
	string mName;
	int mAge;
	void setName(string name){ mName = name; }
	void setAge(int age){ mAge = age; }
	void showStudent(){
		cout << "Name:" << mName << " Age:" << mAge << endl;
	}
};

//2. c++中定义结构体变量不需要加struct关键字
void test01(){
	Student student;
	student.setName("John");
	student.setAge(20);
	student.showStudent();
}

强弱类型

C语言:强类型,弱检查—— 一般就叫做弱类型了
C++:强类型,强检查 —— 真正意义上的强类型

强制转换

在C++,不同类型的变量一般是不能直接赋值的,需要相应的强转。
c代码

typedef enum COLOR{ GREEN, RED, YELLOW } color;
int main(){

	color mycolor = GREEN;
	mycolor = 10;
	printf("mycolor:%d\n", mycolor);
	char* p = malloc(10);
	return EXIT_SUCCESS;
}

c++编译器不能通过上述代码

作用域运算符::

通常情况下,如果有两个同名变量,一个是全局变量,另一个是局部变量,那么局部变量在其作用域内具有较高的优先权,它将屏蔽全局变量。

//全局变量
#include<iostream>
using namespace std;

//全局变量
int a = 10;
int main(){
	//局部变量
	int a = 20;
	//全局a被隐藏
	cout << "a:" << a << endl;
}

在这里插入图片描述
这个例子可以看出,作用域运算符可以用来解决局部变量与全局变量的重名问题,即在局部变量的作用域内,可用::对被屏蔽的同名的全局变量进行访问。

void* p

=
NULL;
2 int* p1 = p; //错误 “初始化”: 无法从“void ”转换为“int
3
4 int
pn = NULL;
5 void
pp = pn; //正确 任意类型的指针都可以自动转为万能指针

NULL和nullptr
NULL是给指针赋值的,表示指针指向的是空,nullptr 出现的目的是为了替代 NULL。
在C语言中NULL会被定义成(void*)NULL,但是C++不允许直接将 void * 隐式转换到其他类型,
NULL 只好被定义为 0。

const
C语言中的冒牌货 :C语言中的const并不是真正的常量,只是表示const修饰的变量为只读。

可以看到常量it的值已经通过指针被间接改变

明明已经通过指针修改了a值,为什么输出却没有变呢?

解释:
C++编译器当碰见常量声明时,在符号表中放入常量,那么如何解释取地址呢?
编译过程中若发现对const使用了&操作符,则给对应的常量分配存储空间(为了兼容C)

const参数不匹配的情况

变量的初始化

在C++中变量的初始化,又有了奇葩的操作(极度猥琐)
1,背景
在C++语言中,初始化与赋值并不是同一个概念:
初始化:创建变量时赋予其一个初始值。
赋值:把对象(已经创建)的当前值擦除,而用一个新值来代替。
2,列表初始化
作为C++11新标准的一部分,用花括号来初始化变量得到了全面应用(在此之前,只是在初始化数 组的时候用到)。列表初始化有两种形式,如下所示:

说明:上述的两种方式都可以将变量a初始化为0。
2.1 局限
当对内置类型使用列表初始化时,若初始值存在丢失的风险,编译将报错,如:
3,直接初始化
如果在新创建的变量右侧使用括号将初始值括住(不用等号),也可以达到初始化效果

三目运算符

c语言三目运算表达式返回值为数据值,为右值,不能赋值。 c++语言三目运算表达式返回值为变量本身(引用),为左值,可以赋值。

int a = 10;
	int b = 20;
	printf("ret:%d\n", a > b ? a : b);
	//思考一个问题,(a > b ? a : b) 三目运算表达式返回的是什么?

	cout << "b:" << b << endl;
	//返回的是左值,变量的引用
	(a > b ? a : b) = 100;//返回的是左值,变量的引用
	cout << "b:" << b << endl;

左右值解释:
在c++中可以放在赋值操作符左边的是左值,可以放到赋值操作符右面的是右值。
有些变量即可以当左值,也可以当右值。
左值为Lvalue,L代表Location,表示内存可以寻址,可以赋值。
右值为Rvalue,R代表Read,就是可以知道它的值。

new/delete和malloc/free

在软件开发过程中,常常需要动态地分配和释放内存空间,例如对动态链表中结点的插入与删除。
在C语言中是利用库函数malloc和free来分配和释放内存空间的。C++提供了较简便而功能较强的运算符
new和delete来取代malloc和free函数。
注意: new和delete是运算符,不是函数,因此执行效率高。
new 和 malloc不要混用
分配内存使用完,记得释放内存(数组和普通变量释放有些微区别)

for循环

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。
因此C++中引入了基于范围的for循环,for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围

特点:
从数组的第一个元素开始,逐个赋值给迭代变量不依赖于下标元素,通用
函 数
内联函数
默认函数
定义函数时可以给形参指定一个默认的值,这样调用函数时如果没有给这个形参赋值(没有对应的 实参),那么就使用这个默认的值。也就是说,调用函数时可以省略有默认值的参数。如果用户指定了 参数的值,那么就使用用户指定的值,否则使用参数的默认值。

小结:
有函数声明时,默认参数可以放在声明或定义中,但不能同时存在

在具有多个参数的函数中指定默认值时,默认参数都必须出现在不默认参数的右边,一旦某个参 数开始指定默认值,它右边的所有参数都必须指定默认值.
也就是说,函数声明时,必须按照从右向左的顺序,依次给与默认值。

占位参数
定义函数时,还可以给函数提供占位参数
占位参数只有参数类型,而没有参数名在函数体内部无法使用占位参数
占位参数也可以指定默认参数

函数重载
函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称 为重载函数。重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,对于程序的可 读性有很大的好处。
不同参数列表:
参数个数不同参数类型不同参数顺序不同
函数重载与返回值类型无关

函数重载可以根据具体的参数去决定调用哪一个函数。

为什么需要函数重载?
试想如果没有函数重载机制,如在C中,你必须要这样去做:为这个maxmum函数取不同的名 字,如maxmum_int、maxmum_string等等。这里还只是简单的几种情况,如果是很多个的话,就需要为实现同一个功能的函数取很多个名字,这样做很不友好!
类的构造函数跟类名相同,也就是说:构造函数都同名。如果没有函数重载机制,要想实例化 不同的对象,那是相当的麻烦!
操作符重载,本质上就是函数重载,它大大丰富了已有操作符的含义,方便使用,如+可用于 连接字符串等!

重载函数的调用匹配规则
为了估计哪个重载函数最适合,需要依次按照下列规则来判断:
精确匹配:参数匹配而不做转换,或者只是做微不足道的转换,如数组名到指针、函数名到指 向函数的指针;
提升匹配:即整数提升(如bool 到 int、char到int、short 到int),float到double
使用标准转换匹配:如int 到double、double到int、double到long double、Derived到
Base、T到void、int到unsigned int;
编译器傻了:如果在最高层有多个匹配函数找到,调用将被拒绝(因为有歧义、模凌两可)

函数重载遇上默认参数
在给重载函数指定默认参数时,要考虑是否会和别的重载函数冲突

s tring
to_string(T val)
在C语言中,我们经常使用字符串,但要对字符串进行操作的时候,我们需要使用一些函数进行操 作,但也非常麻烦,那么在C++中有没有更好的字符串操作方法呢?
不用多说,肯定是有的,C++ 标准库提供了 string 类型,支持C语言字符串所有的操作,另外还增加了其他更多的功能。(现在我们可能还无法透彻地理解string,因为到目前为止我们还没有讨论类和对 象。所以现在粗略地了解下即可,等理解了面向对象的概念之后再回头来理解。)

注意:需要包含头文件#include和命名空间std

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Warm wolf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值