基本数据类型
1字节(B) = 8位(bit)
Type | C/C++ | Java |
---|---|---|
int | 4字节 | 4字节 |
short | 2字节 | 2字节 |
long | 4字节 | 8字节 |
char | 1字节 | 1字节 |
double | 8字节 | 8字节 |
long double | 10字节 | 10字节 |
函数&函数指针
#include <iostream>
void (*funcp)(int* a, int* b);
void point_func(int* a,int* b)
{
*a = 200;
printf("函数指针\n");
}
int main()
{
int a = 10;
int b = 20;
// funcp是一个函数指针,将函数point_func()的地址赋给它
funcp = point_func;
funcp(&a, &b);
printf("a值 %d",a);
}
int *p[3];//指针数组,每个元素都是一个指针
int a[3][4];
int (*p)[4];//数组指针
p=a;//此时p指向a[0][]
p++;//此时p指向a[1][]
结构体、共用体
struct Student{
char a;// 1字节
int b;// 4字节
char c;// 1字节
}s1,s2;// 设在32位系统中,内存对齐后,整个结构体大小为12字节
typedef struct{
int i;
}Students;
共用体:是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。目的:节约内存
union Student{
int i;
int j;
float k;
};
库文件编译
gcc test.c -fPIC -shared/static -o test.so
动态库与静态库区别
静态库文件比较大动态库比较小
静态库需要在编译时被链接在目标代码中,动态库在运行时才会被加载到目标代码
静态库类似于Android中的Module,一旦打包APK需要重新进行编译。
动态库类似于jar包打包是不需要重新进行编译
类的构造和析构、友元函数
C++的Student.h头文件的写法
#pragma once
#ifndef Student_H
#define Student_H
class Student{
int i;//默认私有成员
friend void test();//友元函数
friend class Teacher;//友元类
public:
Student(int i);//构造函数
~Student();//析构函数
private:
int j;//私有成员
protected:
int k;//保护成员
public:
int l;//公有成员
};
#endif // !Student_H
Students.cpp
#include "Student.h"
#include <iostream>
using namespace std;
Student::Student(int i):i(i){ //默认赋值 this->i = i
cout << "构造方法" << endl;
}
Student::~Student(){
cout << "析构方法" << endl;
}
单例对象
// Student.h
class Student{
private:
static Student* instance;
Student();
public:
static Student* getInstance();
};
// Student.cpp
#include "Student.h"
Student* Student::instance = 0;
Student* Student::getInstance(){
if(!instance){
instance = new Student();
}
return instance;
}
// 使用
Student* stu = Student::getInstance();
继承
#include<iostream>
using namespace std;
class Parent{
public:
void method(){
cout<< "parent" << endl;
}
};
class Child1 : Parent{
public:
void method(){
cout<< "child" << endl;
}
};
class Child2 : private Parent{
// 默认继承私有的
};
class Child3 : Child1, Child2{
};
多态
静态多态
Parent* child = new Child();
child->method();// 这里调用的是父类的方法
动态多态
// 虚函数
class Parent{
public:
virtual void method(){
// 子类实例化时会检查父类的方法,从而调用父类的函数
/* 所以构造方法永远不要设为虚函数,析构方法要设为虚函数 */
}
}
// 此外,纯虚函数要在子类中实现
类模板、函数模板
#include<iostream>
// 函数模板
template <typename T>
T methodname(T i, T j){
return i>j?i:j;
}
// 类模板
template <class A, class B>
class C{
public:
A test(A a, B b){
return a + b;
}
}
类型转换
强转类型 | 解释 |
---|---|
const_cast | 字面上理解就是去 const 属性。 |
static_cast | 命名上理解是静态类型转换。如 int 转换成 char |
dynamic_cast | 命名上理解是动态类型转换。如子类和父类之间的多态类型转换。 |
reinterpret_cast | 仅仅重新解释类型,但没有进行二进制的转换 |
4种类型转换的格式,如:TYPE B = static_cast(TYPE)(a)
const_cast
修改类型的const或volatile属性
const char *a;
char *b = const_cast<char*>(a);
char *a;
const char *b = const_cast<const char*>(a);
static_cast
- 基础类型之间互转。如:float转成int、int转成unsigned int等
- 指针与void之间互转。如:float*转成void*、Bean*转成void*、函数指针转成void*等
- 子类指针/引用与 父类指针/引用 转换。
class Parent {
public:
void test() {
cout << "p" << endl;
}
};
class Child :public Parent{
public:
void test() {
cout << "c" << endl;
}
};
Parent *p = new Parent;
Child *c = static_cast<Child*>(p);
//输出c
c->test();
//Parent test加上 virtual 输出 p
dynamic_cast
主要 将基类指针、引用 安全地转为派生类.
在运行期对可疑的转型操作进行安全检查,仅对多态有效
//基类至少有一个虚函数
//对指针转换失败的得到NULL,对引用失败 抛出bad_cast异常
Parent *p = new Parent;
Child *c = dynamic_cast<Child*>(p);
if (!c) {
cout << "转换失败" << endl;
}
Parent *p = new Child;
Child *c = dynamic_cast<Child*>(p);
if (c) {
cout << "转换成功" << endl;
}
reinterpret_cast
对指针、引用进行原始转换
float i = 10;
//&i float指针,指向一个地址,转换为int类型,j就是这个地址
int j = reinterpret_cast<int>(&i);
cout << hex << &i << endl;
cout << hex << j << endl;
cout<<hex<<i<<endl; //输出十六进制数
cout<<oct<<i<<endl; //输出八进制数
cout<<dec<<i<<endl; //输出十进制数
char*与int转换
//char* 转int float
int i = atoi("1");
float f = atof("1.1f");
cout << i << endl;
cout << f << endl;
//int 转 char*
char c[10];
//10进制
itoa(100, c,10);
cout << c << endl;
//int 转 char*
char c1[10];
sprintf(c1, "%d", 100);
cout << c1 << endl;
异常
void test1()
{
throw "测试!";
}
void test2()
{
throw exception("测试");
}
try {
test1();
}
catch (const char *m) {
cout << m << endl;
}
try {
test2();
}
catch (exception &e) {
cout << e.what() << endl;
}
//自定义
class MyException : public exception
{
public:
virtual char const* what() const
{
return "myexception";
}
};
//随便抛出一个对象都可以
文件与流操作
C 语言的文件读写操作
头文件:stdio.h
函数原型:FILE * fopen(const char * path, const char * mode);
path: 操作的文件路径
mode:模式
模式 | 描述 |
---|---|
r | 打开一个已有的文本文件,允许读取文件。 |
w | 打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,程序会从文件的开头写入内容。如果文件存在,则该会被截断为零长度,重新写入。 |
a | 打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,程序会在已有的文件内容中追加内容。 |
r+ | 打开一个文本文件,允许读写文件。 |
w+ | 打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。 |
a+ | 打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。 |
//========================================================================
FILE *f = fopen("xxxx\\t.txt","w");
//写入单个字符
fputc('a', f);
fclose(f);
FILE *f = fopen("xxxx\\t.txt","w");
char *txt = "123456";
//写入以 null 结尾的字符数组
fputs(txt, f);
//格式化并输出
fprintf(f,"%s",txt);
fclose(f);
//========================================================================
fgetc(f); //读取一个字符
char buff[255];
FILE *f = fopen("xxxx\\t.txt", "r");
//读取 遇到第一个空格字符停止
fscanf(f, "%s", buff);
printf("1: %s\n", buff);
//最大读取 255-1 个字符
fgets(buff, 255, f);
printf("2: %s\n", buff);
fclose(f);
//二进制 I/O 函数
size_t fread(void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file);
size_t fwrite(const void *ptr, size_t size_of_elements,
size_t number_of_elements, FILE *a_file);
//1、写入/读取数据缓存区
//2、每个数据项的大小
//3、多少个数据项
//4、流
//如:图片、视频等以二进制操作:
//写入buffer 有 1024个字节
fwrite(buffer,1024,1,f);
C++ 文件读写操作
<iostream> 和 <fstream>
数据类型 | 描述 |
---|---|
ofstream | 输出文件流,创建文件并向文件写入信息。 |
ifstream | 输入文件流,从文件读取信息。 |
fstream | 文件流,且同时具有 ofstream 和 ifstream 两种功能。 |
char data[100];
// 以写模式打开文件
ofstream outfile;
outfile.open("XXX\\f.txt");
cout << "输入你的名字: ";
//cin 接收终端的输入
cin >> data;
// 向文件写入用户输入的数据
outfile << data << endl;
// 关闭打开的文件
outfile.close();
// 以读模式打开文件
ifstream infile;
infile.open("XXX\\f.txt");
cout << "读取文件" << endl;
infile >> data;
cout << data << endl;
// 关闭
infile.close();
容器
#include<iostream>
#include<vector>
#include<set>
using namespace std;
int main(){
// 序列式与关联式
// 序列式容器:元素排列顺序与元素本身无关,由添加顺序决定的stack
// vector、list、dequeue、queue、stack、priority、ueue
vector<int> vec_1;
// 声明有一个元素空间vector<int> vec_2(1);/1/6个元素值都是1
vector<int> vec_3(6, 1);
vector<int> vec_4(vec_3);
// 增加元素
vec_1.push_back(10);
// 通过下标来获得元素
cout << "通过下标来获得元素:" << vec_1[0] << endl;
// 直接获得队首与队尾的元素
vec_1.front();
vec_1.back();
// 清空
vec_1.clear();
vec_1.erase(vec_1.begin(), vec_1.end());
cout << "获得vec的容量大小:" << vec_1.capacity() << endl;
// 关联式 set、map、hashmap
// set 集合,元素不可重复
set<int> set1 = {1, 2, 3, 4};
// insert()插入元素,返回值是一键值对pair
pair<set<int>::iterator, bool> _pair = set1.insert(1);
set<int>::iterator i_b = set1.begin();
set1.end();// 指向最后一个元素的下一个元素NULL
for(; itt != set1.end(); itt++){
cout << *itt << endl;
}
// map
map<int, string> map1;
map<int, string> map2 = {{1, "a"}, {2, "b"}};
return 0;
}
命名空间
//第一个命名空间
namespace spacename1{
void func(){
cout << "Inside"<< endl;
}
}
//第二个命名空间
namespace spacename2{
void func(){
cout << "outsite" << endl;
}
}
// 使同名函数调用不冲突
// using namespace spacename1;
spacename1::func();
spacename2::func();
C++引用
引用 | 指针 |
---|---|
不存在空引用,引用必须连接到一块合法的内存 | 有空指针 |
一旦引用被初始化为一个对象,就不能被指向到另一个对象 | 指针可以在任何时候指向到另一个对象 |
引用必须在创建时被初始化 | 指针可以在任何时间被初始化 |
int i = 17;
int* p = &i;
int& r = i;
cout << "Value of i reference:" << r << endl;