其它的和C相差无几,参照b站cpp课程-哔哩编程学院,菜鸟cpp教程,
【Visual Studio 2022】常用快捷键和一些小技巧。
#include
using namespace std;
class A {
public:
};
class A1 :public A {
};
int main()
{
return 0;
}
cout ;
cout << "Hello World" ;//直接字符串
cout << name ; //字符串地址
<< endl ://换行
cpp中 int x{ }
和 int x = 0
是一回事么?。
int a{10}; //int a=10; 效果一样
int b{ };// int b{0}; int b=0;
return; return 0; return -1; return 1之间的区别。
void test01()
{
ifstream ifs;
ifs.open("test.txt", ios::in);
if (!ifs.is_open())
{
cout << "文件打开失败" << endl;
return; //void函数返回,退出整个程序。
}
}
相比 int 的0,1更节约内存。非0即1,方便判断
#include
using namespace std;
int main()
{
bool a = true; //ture就是1
a = false; //false就是0
a = 123; //非0即1
a = 3.14;
cout << a << endl << sizeof(bool); //长度都是1个字节。
return 0;
}
一般用于简单函数,占用内存不大的。
就函数声明、函数定义前加上关键字:inline
#include
using namespace std;
inline void func(int num); //声明
int main()
{
func(4);
return 0;
}
inline inline void func(int num) { //定义
cout << num ;
}
同一项目,函数名字可以重复。
但函数的参数列表必须不同:不同个数,同个数对应位置类型不同。
只有返回值不同不行!
声明函数某个参数时,指定一个默认值,调用时缺省则默认。
从右到左排!
#include
using namespace std;
void func(int num, float val = 2, double db = 3);//声明处默认
int main()
{
func(4); //调用时 参数缺省
return 0;
}
void func(int num, float val, double db) {
cout << num <<endl << val <<endl << db;
}
指向同一地址,心连心,1变则2变,定义引用的时候必须初始化。
#include
using namespace std;
class Person {
public:
int age;
string name;
};
int main()
{
int a1 = 0;
int a2 = 3;
int& b1 = a1; //int* const b1 = &a1; 使用时直接用b1,用*b1会报错!
int& b2 = a2; //引用变量,必须同时初始化
cout << b1 << endl; //0
cout << b2 << endl; //3
b1++; //心连心
cout << a1 << endl; //1
b1 = a2; //赋值!不能更改引用。
cout << a1 << endl; //3
b1 = b2; //同 b1 = a2,赋值,不能更改引用
b1++;
cout << a1 << endl; //4
cout << a2 << endl; //3
Person Tom;
Person& Tomc = Tom;
Tomc.age = 2;
cout << Tom.age; //2
return 0;
}
#include
using namespace std;
//1. 值传递
void mySwap01(int a, int b) {
int temp = a;
a = b;
b = temp;
}
//2. 地址传递
void mySwap02(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
//3. 加个引用,让形参能够改变实参!
void mySwap03(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int a = 10;
int b = 20;
mySwap01(a, b); //10,20 不能交换
cout << "a:" << a << " b:" << b << endl;
mySwap02(&a, &b);//20,10 指针肯定可以交换
cout << "a:" << a << " b:" << b << endl;
mySwap03(a, b); //10,20 引用也能交换!比指针简洁。
cout << "a:" << a << " b:" << b << endl;
return 0;
}
#include
using namespace std;
//返回局部变量引用
int& test01() {
int a = 10; //局部变量
return a;
}
//返回静态变量引用
int& test02() {
static int a = 20; //静态变量,相当于全局变量!
return a;
}
int main() {
//不能返回局部变量的引用
int& ref = test01(); //局部变量,函数执行完就释放内存了!
cout << "ref = " << ref << endl;
cout << "ref = " << ref << endl;
//如果函数做左值,那么必须返回引用
int& ref2 = test02(); //别名,左右一样
cout << "ref2 = " << ref2 << endl;
cout << "ref2 = " << ref2 << endl;
test02() = 1000; //左值
cout << "ref2 = " << ref2 << endl;
cout << "ref2 = " << ref2 << endl;
return 0;
}
#include
using namespace std;
//1、引用作为重载条件
void func(int& a) //int& a = 10;非法
{
cout << "func (int &a) 调用 " << endl;
}
void func(const int& a)// const int& a = 10;合法,编译器:int noname = 10;int& a = noname;
{
cout << "func (const int &a) 调用 " << endl;
}
int main() {
int a = 10;
func(a); //调用无const
func(10);//调用有const
return 0;
}
命名空间 ::(的)元素
#include
using namespace std; //引入整个空间,内存较大?
// using std::cout;
// using std::endl;
namespace NAME_1 {
namespace NAME_1_1 { // 嵌套
int num = 8;
}
int num=9;
float cal;
void func_1() {
cout << "func1" << endl;
}
void func_2();
}
namespace N = NAME_1;//取别名
void NAME_1::func_2() { //定义命名空间的
cout << "func_2" << endl;
}
int main()
{
int num = 10;
cout << "main"<<endl;
NAME_1::func_1();
NAME_1::func_2();
cout << num<<endl; //10
cout << NAME_1::num << endl;//9
cout << NAME_1::NAME_1_1::num << endl;//8
return 0;
}
直接new一个指针,省去变量名。
申请和释放内存。
#include
using namespace std;
int main()
{
//申请单个内存
int* p1 = new int;
cout << p1 << endl;
cout << &p1 << endl;
*p1 = 0;
cout << *p1 << endl;
//申请单个内存且初始化
int* p2 = new int(666);
cout << *p2 << endl;
//批量申请(连续的内存),不能再给初值。
int* p3 = new int[10];
//释放内存
delete p1; //只有new出来的指针才能delete,否则运行出错!
delete p2;
delete p3;//只能释放一个
delete[] p3;//释放连续的一段,只能向后,必须首地址!
return 0;
}
类 :: 方法。
类修饰词:private,public,protected
#include
#include
#include
using namespace std;
//全局区域
class Sheep {
int age=0; //默认私有,只能在类里面调用
public:
char name[32]; //只能里面直接赋值,外面只能strcpy; 有string类,谁还用c的字符串?
string name2; //cpp特有强大的字符串!
void speak();
void setAge(int n) { // 可以设置,不可以直接访问age
age = n;
}
int getAge() {
return age;
}
private:
int birthday;
void eat() {
cout << "吃" << endl;
}
protected: //继承的而已可以访问
};
void Sheep::speak() { // 类(的)::
cout << "咩" << endl;
}
int main()
{
Sheep xi;
// xi.name = "喜羊羊"; 错误。但类里 string name;外面就可以直接赋值了。
// xi.name[] = "喜羊羊"; 错误
strcpy_s(xi.name,"喜羊羊"); //出来后只能用 strcpy 赋值就离谱。
cout << xi.name << endl ;
xi.speak(); //咩
xi.setAge(12);
cout << xi.getAge() << endl;
//对象指针!!!
Sheep* pxi = ξ
pxi->speak(); //指针肯定指->,对象才用点.
return 0;
}
小写的string !
#include
// #include c语言的,多个.h
#include
using namespace std;
int main()
{
string str; //相比c,更强大的字符串类型!附带字符串处理函数!
str = "abc123"; //赋值
char ch;
ch = str[0]; // 取特点值
cout << ch << endl;
ch = str.at(1);
cout << ch << endl;
cout << str.length()<<endl; //长度
str = "abc12314131313321312312312312312"; //动态长度?随意赋值?
cout << str.length()<<endl;
str.clear();//清空
if (str.empty()) { //判空
cout << "非空" << endl;
}
else {
cout << "空" << endl;
}
string str2 = "串2";
if (str == str2) {//直接等号比较!!!
cout << "同" << endl;
}
else {
cout << "不同" << endl;
}
return 0;
}
cpp 类构造函数 & 析构函数,
类的构造函数:创造对象时自动执行!用来赋值基本属性等很好用
#include
using namespace std;
class Sheep {
public:
int age;
int size;
Sheep() { //必须与类名一样,无返回值,无返回类型,
cout << "默认无参,不写也有的构造函数" << endl;
}//但是,自己写了有参的,默认无参的不写就没了,构造对象时就不能不带参了。
Sheep(int, int any = 0); //也可以初始值,声明变量名也定义的形参名可以不一样!
};
Sheep::Sheep(int age, int size) { //里外定义都可以
cout << "自定义带参构造函数" << endl;
this->age = age;
this->size = size;
}
int main()
{
Sheep xi;
Sheep lan(10, 100); //构造函数就这而已
cout << lan.age << " " << lan.size << endl;
//同理对象指针,直接new省去对象名
Sheep* pmei = new Sheep;
Sheep* pfei = new Sheep(14);//默认0
cout << pfei->age << " " << pfei->size << endl;
return 0;
}
创造对象时自动调用 构造,对象生命结束时自动调用 析构。
但人为调用时,对象没有结束。
对象指针形式的,不会自动调用,必须手动释放内存。
Sheep* pmei = new Sheep;
delete pmei;//只能手动释放内存,才会调用析构函数,释放之后就不能用这个对象(指针)了。
必须public。
~Line(); // 这是析构函数声明
复制对象。
也是类中默认有的
Sheep(const Sheep& obj){}; //默认完全1:1复制,
Sheep(const Sheep& obj,int n){};//复制的基础上,添加属性
Sheep(int a,const Sheep& obj,int n){};//不是拷贝构造了,第一个参数必须对象的引用。
Sheep lan2= lan;
cout << lan2.age << " " << lan2.size << endl;
Sheep lan3(lan); //一样的完全复制
cout << lan3.age << " " << lan3.size << endl;
谁没事会用这些嘛,看得懂就行
this
:形参名和类中变量名相同是使用
类中const
修饰变量初始化,一旦初始化,方法,对象中都不能修改
static
:静态变量,存在类里,类的所有对象共用。
static int num;
Sheep xi;
Sheep lan; //同一个类的对象
xi.num =0; //可以用于创造的对象个数计数。
lan.num=1;//同一个num,一改都改
Sheep::num;//也可以类名直接访问。
静态方法。
static void func();//类中,声明加static
void Sheep::func(){//类外,定义不用加了
//不同访问类中普通成员(包括变量和方法)!不能用this。
//只能访问静态成员
}
Sheep xi;
xi.func();//对象调用
Sheep::func(); //直接类调用,
const
:类中,常量数据,常量函数
const int val; //成员初始化列表赋值 ,否则不能改
static int num;
void func() const{ //后面 加个const
cout<<"func1"<<endl;
//val = 0;等等错误,能访问,但都不能改成员!就保险一点而已。
num = 0;// 但静态成员可以改
}
赋值操作都可用列表的形式给出
省了this->age = age; this->size = size; 不用this了,自动识别。
#include
using namespace std;
class A {
int a1; //private
public:
char* str;
int age;
A(int a1, char* str, int age) :a1(a1), str(str), age(age) {
cout << "A的初始化列表构造"<<endl;
};
void f() {
cout << a1 <<endl << age << endl;
cout << str;
}
};
int main()
{
char s[10] = "123";
A a(1, s, 2);
a.f();
return 0;
}
无需构造函数。
全public可以用{ }直接初始化,有private,protected就不行。
#include
using namespace std;
class A {
public:
char str[100];
int age;
int a2;
void f() {
cout << age;
}
};
int main()
{
A a = { "123",1 };// c11 { }用于初始化对象
a.f();
return 0;
}
无论怎样,都不能继承父类的私有private属性8
public:一般都public继承,父类public,protected不变
protecte:全变protected
private:全变private
废话:父类中私有成员也是被子类继承下去了,只是由编译器给隐藏后访问不到。
Son s;
s.func(); //子类对象
s.Base::func();//子类对象.父类Base::的函数
s.Base::func(10); //重载
加上:静态可用类名访问
Son::func();
Son::Base::func(); //子类::父类::static函数
Son::Base::func(100);
cpp实际开发中不建议用多继承,看见了认识就行。
class Son : public Base2, public Base1
{
}
函数重载:同名不同形参…
同名同参。函数返回值类型 函数名 参数列表 完全一致。
#include
using namespace std;
class A
{
public:
int Func() { //多态1:函数重写,子父类同名函数。
cout << "父A" << endl;
return 0;
}
};
class A1 :public A {
public:
int Func() {
cout << "子A1"<<endl; //相同函数,不同子类,不同实现 => 多态
return 1;
}
};
class A2 :public A {
public:
int Func() {
cout << "子A2" << endl;
return 2;
}
};
int main()
{
A a; //父类可以实例化对象
A1 a1;
A2 a2;
cout << a.Func() << endl; //父A 0
cout << a1.A::Func() << endl; //父A 0,子类对象可以调用父类的函数
cout << a1.Func() << endl;//子A1 1
cout << a2.Func() << endl;//子A2 2
cout << a2.A::Func() << endl; //父A 0
return 0;
}
父类指针或引用指向子类对象。
继承父类virtual虚函数,子类实现,百花齐放。
父类的函数必须vitrual,否则传入子类对象也只能调用父类函数!!
void testFunc1(A& a) { ...... }
testFunc1(a1); //A& a = a1;多态:父类引用 = 子类对象;
testFunc2(&a1);//A* a = &a1;多态:父类指针 = 子类对象地址;
A* pa = new A1;//new指针父类形参
A& pa2 = *(new A2); //*new引用父类形参
delete pa;//父类指针释放子类对象,会释放不干净,需要实现虚析构函数进一步释放。
#include
using namespace std;
class A
{
public:
virtual int Func() { //函数重写:子父类同名同参函数。
cout << "父A" << endl;
return 0;
}
};
class A1 :public A {
public:
int Func() {
cout << "子A1" << endl; //相同函数,不同子类,不同实现 => 多态
return 1;
}
};
class A2 :public A {
public:
int Func() { //父类同名的函数可以不virtual,函数重写而已。
cout << "子A2" << endl;
return 2;
}
};
void testFunc1(A& a) { //A& a = a1;
a.Func(); //父类形参,父类的函数必须vitrual,否则传入子类对象也只能调用父类函数!!
}
void testFunc2(A* a) { //A* a = &a1;
a->Func();
}
int main()
{
A a; //父类可以实例化对象
A1 a1;
A2 a2;
cout << a.Func() << endl; //父A 0
cout << a1.A::Func() << endl; //父A 0,子类对象可以调用父类的函数
cout << a2.A::Func() << endl; //父A 0
cout << a1.Func() << endl;//子A1 1
cout << a2.Func() << endl;//子A2 2
cout << "=========================="<<endl;
//A a = new A1; 不能直接父类形参
A* pa = new A1;
pa->Func(); //子A1,new指针父类形参
A& pa2 = *(new A2);
pa2.Func(); //子A2,*new引用父类形参
cout << "==========================" << endl;
testFunc1(a); // A& a = a;引用别名自己
testFunc1(a1); //A& a = a1;多态:父类引用 = 子类对象;
testFunc1(a2);
testFunc2(&a);
testFunc2(&a1);//A* a = &a1;多态:父类指针 = 子类对象地址;
testFunc2(&a2);
return 0;
}
类似java的接口…
类中只要有一个纯虚函数就称为抽象类:
A a;
,也不能new:A* pa1 = new A1;
。#include
using namespace std;
class A {
virtual int Func() = 0; //纯虚函数
};
class A1 :public A {
};
class A2 :public A {
public:
int Func() {
cout << "A2" << endl;
return 1;
}
};
int main()
{
//A1 a; 抽象类不允许实例化对象,子类没重写,也为抽象类。
A2 a2;
cout<<a2.Func(); //先执行函数,再输出返回值。
//A* pa1 = new A1; 不能new 抽象类!
//A1* pa1 = new A1;
return 0;
}
一般用不上,看到认识就行。
虚析构和纯虚析构共性:
虚析构和纯虚析构区别:
virtual ~Animal() = 0; //1. 父类虚析构
~Cat()
{
cout << "Cat析构函数调用!" << endl;
if (this->m_Name != NULL) {
delete m_Name; //2. 子类析构释放进一步内存
m_Name = NULL;
}
}
写:一次,不用循环
读:每次指定大小读入,每次大小可能不一样,多次就用while循环,直到结束file.read()返回假!
C语言中文网cpp文件,挺详细的
操作文件的三大类:
文件打开方式:
打开方式 | 解释 |
---|---|
ios::in | 为读文件而打开文件 |
ios::out | 为写文件而打开文件 |
ios::ate | 初始位置:文件尾 |
ios::app | 追加方式写文件 |
ios::trunc | 如果文件存在先删除,再创建 |
ios::binary | 二进制方式 |
注意: 文件打开方式可以配合使用,利用|操作符
**例如:**用二进制方式写文件 ios::binary | ios:: out
写到一个txt文件中,没有自动创建
#include
#include //file stream
using namespace std;
int main() {
//写到一个txt文件中,out方式打开,没有就自动创建,重名是直接覆盖!
fstream file;
file.open("test.txt", ios::out);
file << "姓名:李四" << endl << "性别:男" << endl << "年龄:18" << endl;
file.close();
return 0;
}
读一个txt文件,一行一行字符串
#include
#include //file stream
#include
using namespace std;
int main() {
char ch = 97; //数字会ascll转换
cout << ch << endl; //a
char arr[3] = "12";
cout << arr << endl; //12,字符串首地址就会输出真个字符串!
//写到一个txt文件中,in方式打开,需要判断是否打开成功!
fstream file;
file.open("test.txt", ios::in);
if (file.is_open())
{
cout << "文件打开成功" << endl;
}
else {
return -1;//非0,不正常退出
}
char buf[1024] = { 0 }; //最大1024字节,字符串缓冲区
cout << sizeof(buf) << endl; //1024
while (file >> buf) //一行一行读到buf
{
cout << buf << endl; //打印buf整个字符串。
}
file.close();
return 0;//0,执行完毕,正常退出
}
istream& getline (char* s, streamsize n );
istream& getline (char* s, streamsize n, char delim );
从istream中读取至多n个字符(包含结束标记符)保存在s对应的数组中。即使还没读够n个字符。如果遇到delim(默认为’\0’) 或 字数达到限制,则读取终止,delim都不会被保存进s对应的数组中。
#include
#include
using namespace std;
int main() {
fstream file;
file.open("test.txt", ios::in);
if (file.is_open())
{
cout << "文件打开成功" << endl;
}
else {
return -1;//非0,不正常退出
}
char buf[1024] = { 0 }; // sizeof(buf)为1024
while (file.getline(buf,sizeof(buf)))
{
cout << buf << endl;
}
file.close();
return 0;//0,执行完毕,正常退出
}
#include
istream& getline (istream& is, string& str, char delim);
istream& getline (istream&& is, string& str, char delim);
istream& getline (istream& is, string& str);
istream& getline (istream&& is, string& str);
用法和上第一种类似,但是读取的istream是作为参数is传进函数的。读取的字符串保存在string类型的str中。
#include
#include
#include //包含string
using namespace std;
int main() {
fstream file;
file.open("test.txt", ios::in);
if (file.is_open())
{
cout << "文件打开成功" << endl;
}
else {
return -1;//非0,不正常退出
}
//第三种
string sf;
while (getline(file, sf))
{
cout << sf << endl;
}
file.close();
return 0;//0,执行完毕,正常退出
}
一个字符一个字符读,牛!
#include
#include
using namespace std;
int main() {
fstream file;
file.open("test.txt", ios::in);
if (file.is_open())
{
cout << "文件打开成功" << endl;
}
else {
return -1;//非0,不正常退出
}
//第4种
char c;
while ((c = file.get()) != EOF)
{
cout << c;
}
file.close();
return 0;//0,执行完毕,正常退出
}
可以发现,无论怎样,都得先对象后open,可以使用构造器,一步到位。
fstream file("person.txt", ios::out | ios::binary);
cpp二进制读写详细用法。
binary file,bfile,bf。
二进制.读写,一个字节一个字节的读写!(char,8 bit = 1byte)
对象,变量,数组…二进制底层原样保存到文件,原样读出!
一个对象的write(),二进制格式写入文件。
#include
#include
using namespace std;
class A {
public:
int a1;
//char* str; 这样只会保存地址,不会保存数据,下次启动内存释放了,不能用地址得到数据!
char str[100];
};
int main()
{
A a1 = { 1,"你" };//大括号直接赋值初始化!无需构造函数
A a2 = { 2,"你好" };
A a3 = { 3,"你好中国" };
//把对象写入文件
fstream bf("binary.txt", ios::out | ios::binary); //out不用关心文件异常,合并省略open()
bf.write((char*)&a1, sizeof(a1)); //write 二进制
bf.write((char*)&a2, sizeof(a2)); //write 二进制
bf.write((char*)&a3, sizeof(a3)); //write 二进制
bf.close();
return 0;
}
读取一个二进制文件,
每次读到哪里,读多少;读完了返回假。
#include
#include
using namespace std;
class A {
public:
int a1;
char str[100];
};
int main()
{
fstream bf;
bf.open("binary.txt", ios::in | ios::binary);
if (!bf.is_open()) { //读取,必须open并判断
cout << "failure to open file";
return -1;
}
//怎么写的就怎么读!定义对象读出来就是!
A* pa = new A();
while (bf.read((char*)pa, sizeof(*pa))) {
cout << pa->a1 << endl << pa->str;
};
bf.close();
return 0;
}