day1
C++: C语言内容(不专门讲解)
c++基于c语言的扩展, 头文件, 文件后缀, 编译, 输入输出,堆内存,引用,命名空间,函数
类与对象, 封装, 继承,多态
IO流,友元, 运算符重载 ,静态数据, 常量,
模板STL,C++11新特性(auto, lambda,智能指针)
C++开发平台
window–vs2017, vs2019,qtcreator ,g+±-vscode
C++基于c的扩展
第一个c++程序
1-第一个c++程序.cpp
#include <iostream> int main(int argc, char **argv) { std::cout<<"第一个c++程序"<<std::endl; return 0; }
编译:
g++ -o main 1-第一个c++程序.cpp
运行:
gec:$./main 第一个c++程序
从第一个c++程序可以看出与c不同:
1.后缀
.h, .cpp, .cc, .hpp, .cxx
2.头文件
#include <iostream> c++标准输入输出iostream对应c里面stdio.h c++标准库头文件是不带.h 在c++语言中使用标准c库, 1.比如#include <stdio.h> --->#include <cstdio> 2.在c++中使用非标准库 extern "C" { #include "lcd.h" }
3.输入输出
输入cin, 输出cout,在c++里面已经定义好,不需要自己定义,直接可以使用
在使用的时候前面要添加一个std::
比如:输入
int a=0; double b; char c[8]; std::cin >> a; std::cin >> a >> b >> c;
比如:输出
int a=123; double b=23.5; char c[8]="hello"; std::cout << a <<std::endl; //这里的std::endl就相当于换行 std::cout<<a<<" "<<b<<" "<<c<<std::endl;
注意:默认cout,cin只能对基本数据类型,和字符串输入输出,其他自定义类型需要自己重载输出输入运算符
练习:
用c++的输入输出实现学生数据初始化和显示学生信息
#include <iostream> struct Student{ int age; char name[32]; int number; }; int main(void) { struct Student Jack; std::cout<<"请输入学生信息(name age number):"; std::cin>>jack.name>>jack.age>>jack.number; std::cout<<"name:"<<jack.name<<std::endl; std::cout<<"age:"<<jack.age<<std::endl; std::cout<<"number:"<<jack.number<<std::endl; return 0; }
运行效果
gec:$./main 请输入学生信息(name age number):jack 19 1001 name:jack age:19 number:1001
在c++中使用c库函数
- 标准c库函数
直接可以用c++里面自带的头文件比如, cstdio, cstdlib, cstdbool
- 非标准c库函数
自定义的库函数比如:calc.h, calc.c
calc.h
#ifndef _CALC_H #define _CALC_H int add(int a, int b); int sub(int a, int b); #endif
calc.c
#include "calc.h" int add(int a, int b) { return a+b; } int sub(int a, int b) { return a-b; }
main.cpp
#include <iostream> #include "calc.h" int main(void) { int a=0,b=0; std::cin>>a>>b; int c = add(a,b); std::cout<<c<<std::endl; return 0; }
编译:当有c语言源代码可以直接编译
g++ main.cpp calc.c -o main #有c源代码的时候添加头文件不能用extern "C"{#include"calc.h"}
编译:当没有c语言源代码只有c的库
1.把c语言源代码编译成库
gcc -o libcalc.so -shared -fPIC calc.c
2.编译c++程序使用c库
要修改main.cpp
#include <iostream> extern "C" //表示里面的函数是c语言编写并且已经编译成库 { #include "calc.h" } int main(void) { int a=0,b=0; std::cin>>a>>b; int c = add(a,b); std::cout<<c<<std::endl; return 0; }
现在文件如下:
calc.h libcalc.so main.cpp
g++ -o main main.cpp -L./ -lcalc #-L后是库所在的路径, -l后面接库名 ,比如libcalc.so库名就是calc
指针堆内存
指针定义:指针就是地址(内存的编号),32位系统–32位, 64位系统—64位
指针变量:用来存储地址的变量,这个变量占用空间是4字节(32位机器)或8字节(64位机器)
指针变量定义:
数据类型 *变量名称 = 地址;
int *ptr = 0x12345678; //错误
3-c++指针.cpp:6:13: error: invalid conversion from ‘int’ to ‘int*’ [-fpermissive] int *ptr = 0x12345678; ^
注意:指针在赋值的时候必须保证类型一致
如果实现上面ptr赋值
int *ptr = (int *)0x12345678;
堆内存分配
C语言中
申请堆空间malloc, calloc, realloc, 释放堆空间 free
char *str = (char*)malloc(100); free(str);
C++语言中
用new来申请堆空间, delete释放空间
申请堆空间格式:
数据类型 *变量名称 = new 数据类型; //申请一个对象 数据类型 *变量名称 = new 数据类型[n]; //申请n个对象
释放对空格式:
delete 变量名称; delete []变量名称;
例子
char *astr = new char; //申请一个char对象 delete astr; char *bstr = new char('a');//申请一个char对象并且初始化为a delete bstr; char *cstr = new char[100];//申请100个char对象 delete []cstr; int *dint = new int; //申请一个int对象 delete dint;
new == malloc + 构造函数
delete == free + 析构函数
练习:
申请4字节的堆空间, 从终端输入数据初始化空间值, 在用char *str 指向堆空间, 并且把空间中的每一个字节数据输出(整型数)
#include <iostream> #include <cstdio> int main() { #if 0 int *ptr = new int; std::cin>>ptr[0]; //*ptr==ptr[0]; char *str = (char*)ptr; for(int i=0; i<4; i++) { printf("%d\t", str[i]); //std::cout<<(int)str[i]<<std::endl; } delete ptr; #endif int *ptr = new int; std::cin>> std::hex >>ptr[0]; char *str = (char*)ptr; for(int i=0; i<4; i++) { std::cout<< std::hex <<(int)str[i]<<std::endl; } delete ptr; }
命名空间
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Z0F1rlF-1652796910004)(day1.assets/image-20220427165633744.png)]
命名空间作用:名字冲突(函数,变量,类)
定义:
namepace 名称{ 变量, 函数, 类 };
例子:
namespace A { int data; void showA() { cout<<data<<endl; } } namespace B { int data; void showA() { cout<<data<<endl; } }
使用命名空间
第一种方法
空间名称::成员名 (推荐写法)
int main(void) { std::cin>>B::data>>A::data; A::show(); B::show(); }
第二种方法
using指引
using namespace B; //using指引 using namespace std; int main(void) { cin>>data>>A::data; A::show(); show(); }
第三种用法
using 声明
using namespace std; using B::data; //using声明 int main(void) { cin>>data>>A::data; A::show(); B::show(); }
空间嵌套
namespace AAA { int dataA; namespace BBB{ int dataB; namespace CCC{ int dataC; } } } 访问: 直接通过空间名称访问 AAA::dataA; AAA::BBB::dataB; AAA::BBB::CCC::dataC; 用using指引 using namespace AAA; 可以直接访问dataA using namespace AAA::BBB; 可以直接访问dataB using 声明 using AAA::BBB::dataB;
同名空间
file1.h文件
namespace AAA{ int dataA; }
file2.h文件
namespace AAA{ int dataB; }
file1.h和file2.h文件中的AAA空间是同一个
匿名空间
没有名字的空间,空间中的成员可以在本文中直接使用,不能在其他文件中使用相当与c里面的static修饰
namespace{ int data; int number; } int main(void) { data = 123; }
作业
1、简述C++中命名空间的作用。
2、 定义两个命名空间A 和 B 分别在A中和B中定义变量value
在main函数中将两个空间的value打印出来。
3、const int a; 在C++编译器中是否需要初始化,为什么?
4、在c++中怎么使用c库函数
5、c++的常用后缀有那些?
6、说下命名空间的中匿名空间的作用, 以及与c语言中的static的异同
7、结合c++中堆空间分配,测试下系统中最大可以分配多少字节的堆空间
8、根据学过的内容编写一个程序计算栈的开始位置(大概位置)—笔试题目
9、读下面程序是否有问题如果有指出改正,并且输出结果是什么?
char *&get_mem(int size) { char *ptr = new char[size]; return ptr; } char *req_mem(int size) { char ptr[size]; return ptr; } int main() { char *&ptr = get_mem(100); const char *p = "hello world"; memcpy(ptr,p,strlen(p)); cout<<ptr<<endl; char *mptr = req_mem(100); memcpy(mptr,p,strlen(p)); cout<<mptr<<endl; }