一、基本概念
1、什么是C++
C++是C语言的继承,即兼容了C语言面向过程的程序设计能力,又能做面向对象的程序设计。
2.C++的一些基本特点:
(1)C++文件一般以 .cpp 结尾(c plus plus) .cc .C
(2)编译(Liunux环境):
g++ xxx.cpp -o app
(3)C++头文件
C++标准的头文件是没有 .h的
#include <iostream>
C++兼容C语言的头文件:
#include <cstdlib>
#include <stdlib.h>
3.C++兼容大部分C语言(不完全兼容) C++编译器更严格
比如 void * 类型转换成 int * ,在C语言中,无需显性的指定,默认是允许的,在C++中,编译检查的更严格,不允许
C++中main函数的返回值必须为 int
二、输入和输出
1、第一个程序 hello world
#include <iostream> // 输入输出流的头文件
int main(){ // 要求main函数的返回值必须为int
std::cout << "hello" << " world" << std::endl
/* std 命名空间
* :: 是C++ 特有的,叫 作用域限定符
* cout C++给我们提供的输出流对象
* << 流输出运算符,表示向输出流对象输出数据(可以级联使用)
*endl 换行 end line
*/
return 0;
}
//执行结果
linux@Ubuntu1:~$ ./a.out
hello world
2. 输出流cout
cout会自动识别要输出的变量的类型
例:
#include <iostream>
int main()
{
int a = 100;
double b = 3.14;
std::cout << "hello" << " world" << std::endl; //自动识别字符串
std::cout<<a<<std::endl; //自动识别int
std::cout<<b<<std::endl; //自动识别double
return 0;
}
//执行结果
linux@Ubuntu1:~$ ./a.out
hello world
100
3.14
//cout的一些格式化输出
#include <iostream>
#include <iomanip> //要加上头文件
int main()
{
int a = 63;
std::cout<<std::dec<<a<<std::endl; //10进制
std::cout<<std::hex<<a<<std::endl; //16进制
std::cout<<std::oct<<a<<std::endl; //8进制
double d = 3.1415926;
std::cout<<d<<std::endl;
std::cout<<std::setprecision(3)<<d<<std::endl; //保留三位小数
return 0;
}
//执行结果
linux@Ubuntu1:~$ ./a.out
63
3f
77
3.14159
3.14
3. 输入流 cin
#include <iostream>
int main()
{
int a;
std::cout<<"请输入......"<<std::endl
std::cin>>a;
std::cout<<a<<std::endl;
return 0;
}
//执行结果
linux@Ubuntu1:~$ ./a.out
请输入......
159
159
练习:
输入一个字符,如果是大写的,转成小写的,如果是小写的,转成大写的,并输出
#include <iostream>
using namespace std;
int main ()
{
char str;
cout << "空格键退出"<<endl;
do{
cout << "请输入......" <<endl;
cin.get(str);
if(str == '\n') {
cout << "输入为空" << endl;
continue;
}
if (str >= 65 && str <= 90){
cout << "输入为大写字母,转换为小写为: ";
str += 32;
cout.put(str) << endl;
cin.ignore(100,'\n');
}else if(str >= 97 && str <= 122){
cout << "输入为小写字母,转换为大写为: ";
str -= 32;
cout.put(str) << endl;
cin.ignore(100,'\n');
}else{
if(str == 32) break;
cout << "请输入字母" << endl;
cin.ignore(100,'\n');
}
} while(1);
return 0;
}
//执行结果
linux@Ubuntu1:~$ ./a.out
空格键退出
请输入......
a
输入为小写字母,转换为大写为: A
请输入......
A
输入为大写字母,转换为小写为: a
请输入......
z
输入为小写字母,转换为大写为: Z
请输入......
Z
输入为大写字母,转换为小写为: z
请输入......
输入为空
请输入......
二、命名空间(名字空间)
1.作用:
在大型项目的开发中,一般都是多个人同时开发,经常会出现命名冲突
这种冲突,称之为命名污染,
命名空间的作用,就是“防止命名污染”
2.用法:
(1) std::cout
在名字前面加上 命名空间和作用域限定符 std::
C++中标准的名字都是std命名空间中的
(2) using std::cout
在使用前,加上 using 命名空间::名字
在其作用域中,后面使用名字时就不用每次都加了
(3) using namespace std;
表示整个文件中都可以使用 std 命名空间中的所有名字
3.自己写命名空间:
格式:
namespace 命名空间名{
类型 变量名字;
}
例1:
#include <iostream>
using namespace std;
namespace Toy{
char name[32] = "玩具熊";
}
int main(){
cout<< "最爱的玩具是: "<<Toy::name<<endl;
return 0;
}
//执行结果
linux@Ubuntu1:~$ ./a.out
最爱的玩具是: 玩具熊
例2:
#include <iostream>
using namespace std;
namespace Toy{
char name[32] = "玩具熊";
}
using Toy::name;
int main(){
cout<< "最爱的玩具是: "<<name<<endl;
return 0;
}
//执行结果
linux@Ubuntu1:~$ ./a.out
最爱的玩具是: 玩具熊
例3:
#include <iostream>
using namespace std;
namespace Toy{
char name[32] = "玩具熊";
}
using namespace Toy;
int main(){
cout<< "最爱的玩具是: "<<name<<endl;
return 0;
}
//执行结果
linux@Ubuntu1:~$ ./a.out
最爱的玩具是: 玩具熊
例4:
#include <iostream>
using namespace std;
namespace Toy{
char name[32] = "玩具熊";
}
namespace Snack{
char name[32] = "饼干";
}
using namespace Toy;
using namespace Snack;
int main(){
//cout<<name<<endl; 有歧义 是错误的 编译会报错
cout<< "最爱的玩具是 "<<Toy::name<<endl;
cout<< "最爱的零食是 "<<Snack::name<<endl;
return 0;
}
//执行结果
linux@Ubuntu1:~$ ./a.out
最爱的玩具是 玩具熊
最爱的零食是 饼干
例5:
#include <iostream>
using namespace std;
namespace Toy{
char name[32] = "玩具熊";
}
namespace Snack{
char name[32] = "饼干";
}
using namespace Toy;
using namespace Snack;
char name[32] = "小猪佩奇"
int main(){
cout<< "最爱看的动画片是"<<::name<<endl; //没有名字空间的名字 会放在匿名空间空
cout<< "最爱的玩具是 "<<Toy::name<<endl;
cout<< "最爱的零食是 "<<Snack::name<<endl;
return 0;
}
//执行结果
linux@Ubuntu1:~$ ./a.out
最爱看的动画片是 小猪佩奇
最爱的玩具是 玩具熊
最爱的零食是 饼干
例6:
#include <iostream>
using namespace std;
namespace Toy{
char name[32] = "玩具熊";
}
using namespace Toy;
int main(){
char name[32] = "小猪佩奇";
cout<< "最爱看的动画片是 "<<name<<endl; //局部优先原则,优先使用函数内部的名字
return 0;
}
//执行结果
linux@Ubuntu1:~$ ./a.out
最爱看的动画片是 小猪佩奇
例7:
#include <iostream>
using namespace std;
namespace Worker{
namespace Teacher{
char name[32] = "李四";
}
char name[32] = "张三";
}
using namespace Worker::Teacher;//命名空间可以嵌套 --不常用
int main(){
cout<<name<<endl;
return 0;
}
//执行结果
linux@Ubuntu1:~$ ./a.out
李四
命名空间总结:
1.命名空间的使用:
Toy::name
2.命名空间的使用:
using Toy::name;
3.命名空间的使用:
using namespace Toy;
4.使用名字有歧义的时候,需要加上 命名空间名::
5.匿名空间,没有命名空间的名字,都在匿名空间里 访问需要加 ::
::name
6.和局部变量名冲突时,局部优先原则,名字空间中的名字被覆盖
7.名字空间可以嵌套使用-----不常用
C/C++中,函数的外面只能写声明,不能写实现逻辑
所以说,命名空间只对名字起作用
三、C++中的字符串
1.C++中字符串有两种处理方式
1.c风格的:
char *p = "hello world";
char arr[] = "hello world";
2.c++风格:
string 类型;
string str = "hello world";
使用string需要加头文件
#include <iostream>
using namespace std;
#include <string> //如果加了std 此处的string就不是必须的了
int main(){
string s1 = "hello world";
scout << s1<< endl;
return 0;
}
3.string类型的初始化和赋值
1.一个变量
string s1="hello"; //初始化的方式1
string s2("world"); //初始化的方式2
string s3; s3 = s1; //赋值的方式 1 相当于strcpy()
string s4; s4 = "world"; //赋值的方式 2
2.两个变量
string s1="hello";
string s2(s1);
string s3 = s1;
string s4 = s1+s2; //相当于strcat()
4.string类型的比较 == != > < >=
//相当于strcmp()
string s1="hello";
string s2="hallo";
string s3="hello";
if(s1 == s3){
cout<<"s1 == s3"<<endl;//输出
}
if(s1 > s2){
cout<<"s1 > s2"<<endl; //输出
}else if(s1 < s2){
cout<<"s1 < s2"<<endl;
}
return 0;
}
5.对于string类型,有两个重要函数
empty() //判断是否为空 如果为 0:不是空 非0:空
size() //返回字符串的长度 不包含\0
例:
#include <iostream>
#include <string>
using namespace std;
int main(){
string s1 = "hello";
if(s1.empty()){
cout<<"s1 为空"<<endl;
}else{
cout<<"s1 不为空"<<" size:"<<s1.size()<<endl;
}
return 0;
} //结果为 s1 不为空 size:5 -----不包含 \0
6.c风格和C++风格字符串的转换
c++ --> c
string s1 = "hello";
printf("%s",s1.c_str());
// string.c_str() 将C++中的string转换成C中的字符串
C --> C++
C中的字符串自动转换成C++的字符串
int main(){
string s1="hello";
char arr[] = "hello";
if(s1 == arr){
cout<<"yes"<<endl;
}
return 0;
}
7.对string中某一位进行访问
string s1="hello";
s1[1] = 'a'; //支持以下标的形式访问string中的某一位
8.字符串输入的问题
1.cin输入字符串,无法输入有空格的
string s;
cin>>s; //如果输入的是 hello world 那么s中只能存hello
2.getline() //输入字符串 遇到\n 结束
string s;
getline(cin,s);
四、bool类型
C++新增了bool类型, bool是 基本类型
1.表示真或者假的 0 为假 非0为真
bool 变量可赋 true false
bool b = true; //防止魔鬼数字
2.大小 1个字节
例:
int main(){
bool b1 = true;
bool b2 = false; //bool类型的变量 可以用 false 和 true 赋值
bool b3 = 10; //bool类型的变量也可以赋值数字
bool b4 = 0; bool b5 = -10; //0为假 非0为真 (即使是负数,也为真)
cout<<"bool_size : "<<sizeof(b1)<<endl; //bool类型大小为 1 字节
cout<<"b1 : "<<b1<<endl; //输出bool变量的值 输出时,
cout<<"b2 : "<<b2<<endl; //真为 1 假为0
cout<<"b3 : "<<b3<<endl;
cout<<"b4 : "<<b4<<endl;
cout<<"b5 : "<<b5<<endl;
cout<<"b5 : "<<boolalpha<<b5<<endl; //以字母的形式输出(true和false)
//一旦设置后,后面的输出全是字母类型
cout<<"b2 : "<<b2<<endl;
cout<<"b5 : "<<noboolalpha<<b5<<endl; //改回以 0 1 的方式输出
//一旦设置后,后面的输出全是0 1 方式
cout<<"b2 : "<<b2<<endl;
bool sex = 0; //女
cout<<"sex:"<<(sex?"帅哥":"美女")<<endl; //bool变量用在三目运算符中
return 0;
}
五、引用(quote)
1.概念:
C++对C的一个重要的扩充,相当于给变量起别名。 ----相当于硬链接
2.定义引用:
& 引用的声明符
类型名 &引用变量名 = 被引用的变量名
例:
#include <cstdio>
int main(){
int a = 100;
int &b = a;
cout<<"a : "<<a<<endl;//100
cout<<"b : "<<b<<endl;//100
printf("&a : %p\n",&a);//
printf("&b : %p\n",&b);//和a的地址相同
return 0;
}
使用引用的要求:
1.定义引用时必须指定被引用的目标 ----定义引用必须要初始化
2.引用类型必须和被引用的类型保持一致
3.引用一旦被初始化,后面便不能修改引用的目标了
3.引用做形参 ----不用考虑值传递地址传递的问题了
例1:引用变量
#include <iostream>
using namespace std;
void function(int &aa){
aa = 200;
}
int main(){
int a = 100;
cout<<"a:"<<a<<endl;
function(a);
cout<<"a:"<<a<<endl;
return 0;
}
例2:引用指针
#include <iostream>
using namespace std;
#include <cstdio>
#include <cstdlib>
void function(int* &aa){
aa = (int *)malloc(sizeof(int));
}
int main(){
int *p = NULL;
function(p);
*p = 100;
cout<<*p<<endl;
return 0;
}
4.常引用
int main(){
int a = 100;
const int &q = a;
a = 200; //正确的,可以通过a修改值
q = 200; //错误的,q是被const修饰的引用(是只读的)
//不能通过q修改值
const int &q1 = 200;//const修饰的引用 可以引用常量
return 0;
}
5.引用做函数的返回值
1.不可以返回局部变量的引用
2.可以返回全局变量或者static修饰的局部变量的引用
3.引用作为返回值,函数的返回值是一个左值
为了防止对函数的返回值进行乱改,一般返回 const 修饰的引用
#include <iostream>
using namespace std;
const int &find_max(int x,int y){
static int temp = x>y?x:y;
return temp;
}
int main(){
int ret = 5;
find_max(10,20) = ret; //如果返回的不是const 修饰的引用,
//那么此处函数的返回值可以被修改
return 0;
}
6.结构体中定义引用:
struct __STU{
int &q;
};
int main(){
int a = 100;
struct __STU s1; //错误
struct __STU s2 = {a}; //如果结构体中有引用成员,定义变量时,必须初始化
return 0;
}
引用和指针的区别?
1.引用必须初始化,指针可以不初始化;
2.指针可以改变指向,引用不能改变引用的对象;
3.存在指向NULL的指针,不存在引用NULL的引用;
4.指针使用时需要做非NULL检查,引用不用;
5.可以定义指针数组、不可以定义引用数组
int a = 10,b = 20;
int *arr[2] = {&a, &b} //正确
------------------------------------
int &arr[2] = {a, b} //错误
6.可以定义数组指针,也可以定义数组引用 (但是有点区别:数组引用不能指向二维数组,如下例子)
int arr[2][2] = {10,20,30,40};
int (*arr_p)[2] = arr;
-----------------------------------
int arr[2] = {10,20};
int (&arr_p)[2] = arr;
7.可以定义指针函数,也可以定义引用函数
int *func_p(int a, int b){}
-----------------------------------
int &func_p(int a, int b){}
8.可以定义函数指针,也可以定义函数引用
int func(int a, int b){}
int (*func_p)(int a, int b);
func_p = func;
------------------------------------
int (&func_r)(int a, int b) = func;
9.可以定义指针的指针(二级指针) 不可以定义引用的引用(二级引用)
int a = 100;
int *p = &a;
int **pp = &p;
---------------------------------
int a= 100;
int &r = a;
int &&rr = r; //错误
int &&r = 100; // 可以 叫做右值引用,(常引用)
C++11以上版本的编译器才支持这种用法
g++ ***.cpp -std=c++11
有的同学的电脑是
g++ ***.cpp -std=c++0x