C++杂记
new和引用&
int main() {
int res=test(1);
//在堆区创建整形数据的数组,需要手动delete,否则内存泄露
int* arr=new int[10];
for(int i=0;i<10;i++){
arr[i]=i;
}
delete[] arr;
cout<<endl;
int a=1;
//a b均指向同一地址,改一则二动
//必须在创建int&时必须初始化,=能赋值操作不能更改引用
int &b=a;
b=2;
int c=1;
const int& d=c;
//d=2 const修饰后d就不能修改
return 0;
}
函数重载和占位符
// 有默认值参数后面需要有默认值
// 函数声明和函数中默认值只能出现一次
int test(int num1,int num2,int num3=3);
// 占位符不能出现在函数声明中,并且占位符可以有默认值,在函数调用时不用手动赋值
int test(int num1,int ,int num2,int num3,int=4){
return num1+num2+num3;
}
// 函数重载只与形参列表中个数,顺序和类型有关,函数返回值不与重载有关
int test(int num1,int num2=2){
return num1+num2;
}
// 函数重载调用时要注意调用的是哪一个,不能出现调用不明确现象
//const只有修饰引用时才能作为重载条件
void test(const int& num){
cout<<"const int num"<<endl;
}
void test(int &num){
cout<<"int num"<<endl;
}
int main() {
int a=0;
test(a);//调用int& 变量传值首先选择int&,不是const int&
test(1);//调用const int& 说明const int&可以直接赋值常数
return 0;
}
类
权限修饰
public 能继承给子类,子类和类外均可访问
protected 能继承给子类,子类可访问,类外不可访问
private 能继承给子类,子类和类外均不可访问
类中变量默认private
构造和析构函数
构造函数就是java中的构造器
析构函数是创建对象后销毁对象前最后运行的代码,特点是:前加 ’ ~ ’ ,无参数,无返回值,不可发生重载,自动被调用,只能调用一次
类中自动提供:
1.空参构造器(自定义其他构造器后则不存在,拷贝构造器同)
2.拷贝构造器(只有一个参数为类本身,对于所有的属性进行拷贝)
3.空函数体的析构函数
Person() {
}
Person(Person&person){
//属性拷贝
}
~Person() {
}
当类中出现其他类成员变量时,成为对象成员,构造顺序是先调用对象成员构造器,后调用本类构造器,析构函数顺序相反
//在创建对象调用空参构造器时,不能加(),否则会被编译器认为函数声明,不会认为创建对象
Person p();//函数声明
Person p;//创建对象
#include <iostream>
#include <string>
#include <list>
using namespace std;
class Person{
private:
string name="";
int age=0;
public:
Person() {}
Person(int age):age(age){}
Person(const string &name, int age) : name(name), age(age) {}
friend ostream &operator<<(ostream &os, const Person &person) {
os << "name: " << person.name << " age: " << person.age;
return os;
}
};
int main() {
Person();//匿名对象的创建,创建后立即销毁
Person person1;//空参构造
Person person2("aa",11);
Person person3=Person();//空参构造
Person person4=Person("bb",11);
Person person5=12;//隐式转换法创建对象,值允许一个参数才能使用
return 0;
}
类中new注意事项
堆开辟空间需要自己提拷贝函数,防止浅拷贝
#include <iostream>
#include <string>
using namespace std;
class Person{
public:
int* age;
Person(int age) {
this->age=new int(age);
}
Person(Person&person){
//this->age=person.age;
this->age=new int(*person.age);
}
~Person() {
if(age!=NULL){
delete this->age;
age=NULL;
}
}
};
int main() {
Person person(12);
// 通过拷贝函数中的this->age=person.age;赋值就会造成两个Person类中的age属性同时指向同一地址
// 在调用析构函数时对同一地址进行delete,就会报错,所以在拷贝构造时通过this->age=new int(*person.age);进行赋值
Person person1=person;
return 0;
}
对象的初始化方式
class Person{
public:
string name;
int age;
//初始化列表初始化属性,在参数列表中填入初始化值
//形参列表中属性可以不写,这样就会造成也可以使用空参构造器,两用
Person(string name, int age) : name(name), age(age) {
}
};
static
static修饰的变量方法和没有static修饰的方法都不属于单个对象,只有没有static修饰的属性属于单个类
class Person{
public:
//编译阶段分配内存
//类内声明,类外初始化,共享同一份数据,并不属于某一个对象
static int num;
static void fun(){
//静态方法只能访问静态变量
num=0;
cout<<"num = "<<num<<endl;
}
};
//需要先定义声明static变量的存在,才能在main函数中调用赋值
int Person::num=0;
int main() {
Person person;
//两种对static变量进行赋值操作
person.num=1;
Person::num=2;
//两种对static方法进行调用
person.fun();
Person::fun();
return 0;
}
this和const修饰的类和方法
class Person{
public:
int age;
Person(int age):age(age) {}
void show(){
cout<<"我是没有this关键字的方法"<<endl;
}
//this本质是常量指针:Person * const this 所以指向不能改变
//方法后增加const变成常方法,会使this变成const Person * const this使this指向的值也不能改变
void showAge()const{
//this->age=2;报错
//this=NULL;报错
cout<<"我会调用this关键字,age = "<<this->age<<endl;
}
};
int main() {
Person* person=NULL;
//空指针对象可以调用类中不涉及属性的方法
person->show();
空指针对象不可以调用类中不涉及属性的方法,会空指针异常
//person->showAge();
//const修饰是常对象,只能调用常方法,因为其他方法可能会改变属性
const Person person1(3);
person1.showAge();
return 0;
}
friend
友元全局函数
友元类
class Person{
//允许访问私有权限
friend void test(Person&person);
friend class GoodPerson;
private:
int age;
public:
Person(int age):age(age){
}
};
class GoodPerson{
public:
GoodPerson(){
}
void play(Person&person){
cout<<"age of person is "<<person.age<<endl;
}
};
void test(Person&person){
cout<<"age of person is "<<person.age<<endl;
}
int main() {
Person person(12);
test(person);
GoodPerson goodPerson;
goodPerson.play(person);
Person person1(11);
return 0;
}
友元成员函数(严格按照这种顺序)
#include <iostream>
#include <string>
using namespace std;
class Person;
class GoodPerson{
public:
GoodPerson(){
}
void play(Person&person);
};
class Person{
friend void GoodPerson::play(Person&person);
private:
int age;
public:
Person(int age):age(age){
}
};
void GoodPerson::play(Person&person){
cout<<"age of person is "<<person.age<<endl;
}
int main() {
Person person(12);
GoodPerson goodPerson;
goodPerson.play(person);
return 0;
}
operator
运算符重载也可以发生函数重载
+
class Person{
public:
int age;
int num;
Person(int age,int num):age(age),num(num){
}
Person operator+(Person&person){
Person temp(person.age+this->age,person.num+this->num);
return temp;
}
};
/*
全局函数重载 + 号
Person operator+(Person&p1,Person&p2){
Person temp(p1.age+p2.age,p2.num+p2.num);
return temp;
}
使用的两种方法:
Person p=operator+(p1,p2);
Person p=p1+p2;
重载举例:
Person operator+(Person&p,int num){
Person temp(p.age,p.num+num);
return temp;
}
*/
int main() {
Person p1(1,3);
Person p2(1,3);
//两种使用方式
Person p3=p1.operator+(p2);
Person p4=p1+p2;
return 0;
}
<<
class Person{
public:
int age;
int num;
Person(int age,int num):age(age),num(num){
}
//类内部重载<<
friend ostream &operator<<(ostream &os, const Person &person) {
os << "age: " << person.age << " num: " << person.num;
return os;
}
};
/*
全局函数重载 << 号
ostream &operator<<(ostream &os, const Person &person) {
os << "age: " << person.age << " num: " << person.num;
return os;
}
*/
int main() {
Person p1(1,3);
Person p2(1,3);
operator<<(operator<<(cout,p1),p2);
cout<<p1<<p2 <<endl;
return 0;
}
++
class Person{
public:
int age;
int num;
Person(int age,int num):age(age),num(num){
}
//前置++
Person& operator++(){
//this->num++;
(*this).num++;
return *this;
}
//后置++
Person operator++(int ){
Person temp=*this;
this->num++;
return temp;
}
friend ostream &operator<<(ostream &os, const Person &person) {
os << "age: " << person.age << " num: " << person.num;
return os;
}
};
int main() {
Person p1(1,3);
Person p2(1,3);
cout<<p1<<++p1<<endl;
return 0;
}
== !=
class Person{
public:
int age;
int num;
Person(int age,int num):age(age),num(num){
}
bool operator==(Person& person){
if(this->num==person.num&&this->age==person.age)
return true;
else
return false;
}
bool operator!=(Person& person){
return !this->operator==(person);
}
friend ostream &operator<<(ostream &os, const Person &person) {
os << "age: " << person.age << " num: " << person.num;
return os;
}
};
int main() {
Person p1(1,3);
Person p2(1,3);
bool a=p1==p2;
bool b=p1!=p2;
cout<<a<<b<<endl;
return 0;
}
继承方式
构造顺序
先造父类后造子类,子类先销毁父类后销毁
重名属性和方法
class Person{
public:
int age;
Person(){}
void show(){
cout<<"父类show"<<endl;
}
static void showStatic(){
cout<<"static 父类方法"<<endl;
}
};
class Student:public Person{
public:
int age;
Student(int age):age(age){
//同java,父类要有空参构造器
}
void show(){
//同名调用父类要添加作用域,方法同
cout<<age<<Person::age<<endl;
}
};
int main() {
Student s1(17);
s1.show();
//调用父类方法添加作用域
s1.Person::show();
//静态方法
s1.showStatic();
Student::Person::showStatic();
return 0;
}
菱形继承
class Person{
public:
int age;
};
class Man: public Person{};
class Woman: public Person{};
class Student:public Man,public Woman{};
int main() {
Student student;
student.Man::age=1;
student.Woman::age=2;
return 0;
}
using namespace std;
class Person{
public:
int age;
};
class Man:virtual public Person{};//虚继承,Person为虚基类
class Woman:virtual public Person{};
class Student:public Man,public Woman{};
int main() {
Student student;
//virtual修饰后只存在一个变量,被两类公用,下面三种均值一个
student.Man::age=1;
student.Woman::age=2;
student.age=3;
//地址相同
cout<<&(student.Man::age)<<'\n'<<&(student.Woman::age)<<'\n'<<&(student.age)<<endl;
return 0;
}
多态virtual
class Person{
public:
int* age;
Person(){
this->age=new int(17);
}
//有一个virtual修饰的方法该类就是抽象类,无法被实例化,子类要重写该virtual方法
virtual void show()=0;
//纯虚析构需要声明也需要实现
virtual ~Person()=0;
};
Person::~Person() {
delete this->age;
cout<<"Person虚构函数"<<endl;
}
void Person::show() {
cout<<"父类show方法"<<endl;
}
class Student:public Person{
public:
int *num;
Student(){
num=new int(1);
}
void show(){
cout<<"子类重写的方法"<<endl;
}
~Student(){
delete num;
cout<<"Student虚构函数调用"<<endl;
}
};
int main() {
//多态:若重写的不是virtual方法,运行的是父类,只有virtual才运行子类
//virtual修饰后,父类可在类外进行父类方法定义
//父类指针在调用析构函数时,不会调用子类析构函数,导致子类如果堆区有属性,会内存泄漏
//为解决子类内存泄漏,需要将父类析构函数进行virtual修饰,并在类外进行析构函数定义,这样也会运行子类析构函数
Person* person= new Student();
(*person).show();
person->Person::show();
delete person;
return 0;
}
IO
文本文件
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main() {
ofstream ofs;
ofs.open("test.txt",ios::out);
ofs<<"aaaa"<<endl;
ofs.close();
ifstream ifs;
ifs.open("test.txt",ios::in);
if(!ifs.is_open()){
cout<<"打开失败"<<endl;
return 0;
}
string buf;
while (getline(ifs,buf)){
cout<<buf<<endl;
}
/*
另外三种
char buf[1024]={0};
while (ifs.getline(buf,sizeof (buf))){
cout<<buf<<endl;
}
char buf[1024]={0};
while (ifs>>buf){
cout<<buf<<endl;
}
char buf;
while ((buf=ifs.get())!=EOF){
cout<<buf;
}
*/
ifs.close();
return 0;
}
二进制文件
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
class Person{
public:
string name;
int age;
Person() {}
Person(string name, int age) : name(name), age(age) {}
friend ostream &operator<<(ostream &os, const Person &person) {
os << "name: " << person.name << " age: " << person.age;
return os;
}
};
int main() {
//写入文件
ofstream ofs("test.txt",ios::out|ios::binary);
Person person("aaa",12);
ofs.write((const char *)&person,sizeof(person));
ofs.close();
//读入数据
ifstream ifs("test.txt",ios::in|ios::binary);
if(!ifs.is_open()){
cout<<"打开失败"<<endl;
return 0;
}
Person p;
ifs.read((char*)&p,sizeof (p));
cout<<p<<endl;
ifs.close();
return 0;
}
模板
模板的调用
#include <iostream>
#include <string>
using namespace std;
//typename可换成class
template<typename T>
void sway(T&a,T&b){
T temp=a;
a=b;
b=temp;
cout<<"template"<<endl;
}
void sway(int&a,int&b){
int t=a;
a=b;
b=t;
cout<<"int sway"<<endl;
}
int main() {
int a=1, b=2;
sway(a,b);//用的int sway
cout<<a<<b<<endl;
sway<>(a,b);//用的template sway
cout<<a<<b<<endl;
sway<int>(a,b);//用的template sway
cout<<a<<b<<endl;
char c='a';
char d='b';
sway(c,d);//用的template sway
cout<<c<<d<<endl;
return 0;
}
类模板
#include <iostream>
#include <string>
using namespace std;
template<typename T,typename E>
class Person{
public:
T name;
E age;
Person(T name,E age):name(name),age(age){}
void showType(){
cout<< "T 类型为"<<typeid(T).name()<<endl;
cout<< "E 类型为"<< typeid(E).name()<<endl;
}
friend ostream &operator<<(ostream &os, const Person &person) {
os << "name: " << person.name << " age: " << person.age;
return os;
}
};
//传参方式1:
void test1(Person<string,int>&person){
cout<<person<<endl;
}
//传参方式2:
template<class T1,class T2>
void test2(Person<T1,T2>&person){
cout<<person<<endl;
}
//传参方式3:
template<class T>
void test3(T&person){
cout<<person<<endl;
}
int main() {
//<string,int>不能省略
Person<string,int> person("小明",12);
person.showType();
test1(person);
test2(person);
test3(person);
return 0;
}
模板的继承
#include <iostream>
#include <string>
using namespace std;
template<typename T,typename E>
class Person{
public:
T name;
E age;
Person(){}
Person(T name,E age):name(name),age(age){}
};
template<typename T,class T1>
class Student:public Person<string,T1>{
public:
T grade;
Student(string name, T1 age, T grade){
this->name=name;
this->age=age;
this->grade=grade;
}
};
int main() {
Person<string,int> person("小明",12);
Student<int ,int >student("小红",17,9);
return 0;
}
string
string赋值
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1;
string s2(2,'w');
string s3(s2);
const char * arr="aaa";
string s4(arr);
cout<<s1<<endl;//空
cout<<s2<< endl;//ww
cout<<s3<<endl;//ww
cout<<s4<<endl;//aaa
return 0;
}
string方法
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1="aaa";
string s2="bbb";
s1+=s2;
s1+s2;
s1.append("111");
s1.append("2222",3);//前三个
s1.append("abcdef",1,2);//从1开始的后两个
int pos=s1.find("11");
s1.find("11",3);
s1.rfind("2");//右
cout<<s1<<endl;
s1.replace(1,3,"wwwww");//1到3包括三换成wwwww
int a=s1.compare(s2);//比较大小
int b=s1.size();
s1.insert(1,"aaaaaaaa");
s1.erase(1,3);//从一开始后三个元素
string s=s1.substr(1,2);//下标为1后的两个
return 0;
}
vector
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void print(vector<int>v){
for(int i : v){
cout<<i<<endl;
}
cout<<endl;
/*
for(vector<int>::iterator iterator=v.begin();iterator!=v.end();iterator++){
cout<<*iterator<<endl;
}
*/
}
int main() {
vector<int> v1{1,2,3,4};
vector<int> v2(v1.begin(),v1.end());
vector<int> v3(2,4);//3个4
vector<int> v4(v2);
print(v4);
v4.resize(10);//指定大小
v4.capacity();//容量
v3.size();//大小
int c=v1.back();//最后一元素
v1.swap(v2);//交换
v1.swap(v2);//可以收缩内存
return 0;
}
list(链表)
size()
empyt()
resize()
push_back()
pop_back()
push_front()
pop_front()
insert()
clear()
erase()
remove()
迭代器支持iterator++或- -
不支持随机