C++核心语法

一、函数重载和默认参数

#include<stdio.h>
#include<iostream.h>
void func(int a=0,int b){//
	printf("%d %d",a,b);
}
void func(string a,string b){
	printf("%s %s",a,b);
}
//函数重载:函数名相同,但是函数参数以及返回类型有一个不同就可以发生函数重载
int main(){
	func(1,2);
	func("123","abc");
}

二、 内存空间管理(new,delete)

int main(){
	int *p=new int;//申请一个int型空间
	delete p;
	char *p=new char[10];//申请10个char空间
	delete [] p;
]

三、类和对象

类的申明

class A{
public:
	A(){//构造函数
		a=100;
	}
	A(int data):a(data){
	
	};
	~A(){//析构函数
		
	}
	void func(void);
private:
	int a;
protect:
}
//类外申明函数
void A::func(void){
	printf("%d",a);
}

浅拷贝和深拷贝

浅拷贝:单纯的文本赋值,默认构造函数就是浅拷贝
深拷贝:在堆区创建新的内存空间,再把数据赋值(主要是类中有指针数据时需要注意)、

#include<iostream>
#include<string>
using namespace std;

class persion{
public:
   persion(){};

   persion(int age,int height){
    this->age=age;
    *m_height=height;
   }

   persion(const persion &p){
    age=p.age;
    m_height=new int(*p.m_height);
   }

  ~persion(){
    if (m_height!=NULL)
    {
     delete m_height;
     m_height=NULL;
    }
    
  };
private:
    string name;
    int age;
    string number;
    int* m_height;
    
};

void test(){
    persion p1(10,160);
    persion p2(p1);//如果采用浅拷贝的方式,
                //那么在调用结束时会对m_height所指的内存空间进行重复的释放,从而报错、
                //因此采用深拷贝方式,让p2这个对象中的m_height指向新的内存空间就不会出现上述问题,所以需要对拷贝函数重写
};

int main()
{
    test();

}

静态成员

#include<iostream>
#include<string>
using namespace std;

class persion {
public:
    /*
      静态成员变量;
      1.静态成员变量在类内申明,类外初始化(出了类定义就是类外)
      2.所有对象共享同一个静态成员变量
      3.静态成员变量也拥有访问权限
    */
    static int age;
    int number;

    /*
    静态成员函数:
    1.所有对象共享同一个静态成员函数
    2.静态成员函数只能调用静态成员变量,不能调用非静态变量
    3.静态成员函数业也有访问权限
    */
    static void fun() {
        m_height = 100;
        //number=10;因为静态成员函数是共享的,所以无法区分是哪一个对象调用非静态成员
    }
private:
    static int m_height;

};

int persion::age = 100;
int persion::m_height = 200;

void test() {
    persion p1;
    persion p2;
    
    /*
    p1.m_height p2.m_height这样是无法访问的(静态成员也有访问权限问题)
    */
    p1.age = p2.age = 100;
    p1.fun();
    //静态成员变量还可以通过类名访问
    int a = persion::age;
    persion::fun();

};

int main()
{
    test();

}

常成员

#include<iostream>
#include<stdio.h>


class A {
public:
	A(int data) :b(data) {//常成员赋值
	
	}
	void func(void)const {
		printf("%d", b);
		//a = 100;常函数不能修改成员的值
	}

private:
	const int b;
	int a;
};

友元

1.全局函数做友元
2.类做友元
3.成员函数做友元
成为友元后可以访问私有权限的数据

#include<iostream>
#include<string>
using namespace std;

class Buliding {
    friend void visit(Buliding& buliding);//全局函数做友元
    friend void GoodGay::gvisit();//成员函数做友元
    //friend class GoodGay;//类做友元
public:
    Buliding();
public:
    string m_SittingRoom;

private:
    string m_BedRoom;
};
Buliding::Buliding() {//构造函数在类外定义
    m_SittingRoom = "客厅";
    m_BedRoom = "卧室";
};


class GoodGay {
public:
    GoodGay();
    void gvisit();

    Buliding* buliding;

};

GoodGay::GoodGay() {
    buliding = new Buliding;

}
void GoodGay::gvisit() {
    cout << buliding->m_SittingRoom << endl;
    cout << buliding->m_BedRoom << endl;
}



void visit(Buliding& buliding) {//全局函数
    cout << buliding.m_SittingRoom << endl;
    cout << buliding.m_BedRoom << endl;
}

int main()
{
    Buliding bulid;
    visit(bulid);
	GoodGay gg;
	gg.gvisit();
}



四、运算符重载

1.加号运算符重载

#include<iostream>
#include<string>
using namespace std;
class persion{
public:
  persion(){
    m_a=10;
    m_b=20;
  }
  //1.成员函数实现运算符重载
  // persion operator+(persion &p){     
  //   persion temp;
  //   temp.m_a+=p.m_a;
  //   temp.m_b+=p.m_b;
  //   return temp;
  // }

  /*
   persion persionADDpersion(persion &p){运算符重载的实质就是成员函数名的更换
    persion temp;
    temp.m_a+=p.m_a;
    temp.m_b+=p.m_b;
    return temp;
  }
  */

  int m_a;
  int m_b;
};

// 2.全局函数的运算符重载
persion operator+(persion p1,persion p2){
  persion temp;
  temp.m_a=p1.m_a+p2.m_a;
  temp.m_b=p1.m_b+p2.m_b;
  return temp;
}

persion operator+(persion p1,int num){
  persion temp;
  temp.m_a=p1.m_a+num;
  temp.m_b=p1.m_b+num;
  return temp;
}

int main()
{
  persion p1;
  persion p2;
  persion p3=p1+p2;

  //成员函数实现运算符重载的实质
  //persion p3=p1.operator+(p2);

  //全局函数实现运算符重载的实质
  //persion p3=operator+(p1,p2);

  //运算符重载实质就是函数,因此可以发生函数重载
  persion p4=p1+100;

}

2.左移运算符重载

#include<iostream>
#include<string>
using namespace std;
class persion{
  friend ostream& operator<<(ostream& cout,persion &p1);//采用友元的方式访问私有权限数据
public:
  persion(){
    m_a=10;
    m_b=20;
  }

private:
  int m_a;
  int m_b;
};
//只能利用全局函数实现左移运算符的重载
ostream& operator<<(ostream& cout,persion &p1){//由于ostream这个类对象只能有一个,
                                                //不能创建一个新的对象,因此全部采用引用的方式来进行传递
      cout<<p1.m_a<<" "<<p1.m_b;
      return cout;
}

int main()
{
  persion p1;
  cout<<p1<<endl;

}



3递增运算符重载

#include<iostream>
using namespace std;


class MyInteger{
	friend ostream& operator<<(ostream& cout, MyInteger myinteger);
public:
	MyInteger() {
		m_a = 0;
	}
	//前置运算符重载
	MyInteger& operator++() {
		m_a++;
		return *this;
	}

	//后置运算符重载
	MyInteger operator++(int) {//利用int占位符来区分前置和后置,而且只能用int来区分
		
		//先存储之前的结果
		MyInteger temp;
		temp = *this;//*this就是其本身
		//++
		m_a++;
		//返回之前的结果
		return temp;
	}

private:
	int m_a;	
};

ostream& operator<<(ostream& cout, MyInteger myinteger) {
	cout << myinteger.m_a;
	return cout;
}

int main() {
	MyInteger a;
	
	cout << a << endl;
	cout << ++a << endl;
	cout << a++ << endl;
	cout << a << endl;


}

4赋值运算符重载(深拷贝,浅拷贝问题)

#include<iostream>
using namespace std;

class persion {

public:
	persion(int age) {
		m_age = new int(age);
	}

	~persion() {
		delete m_age;
	}
	persion& operator=(persion& p){//返回值为persion&,实现程序可以连=操作,
		//先判断是否有数据开辟在堆空间
		if (m_age != NULL) {
			delete m_age;
		}
		m_age = new int(*p.m_age);
		return *this;
	}
	int* m_age;
};


int main() {
	persion p1(10);
	persion p2(20);
	persion p3(30);



	p3=p2 = p1;
	cout << *p1.m_age << endl;
	cout << *p2.m_age << endl;
	cout << *p3.m_age << endl;


}

关系运算符重载和上述差不多

5函数调用重载(仿函数)

#include<iostream>
using namespace std;

class myprintf {
public:
	void operator()(string str) {
		cout << str << endl;
	}
};
class myadd {
public:
	int operator()(int num1,int num2) {
		return num1 + num2;
	}
};


int main() {
	myadd madd;
	cout << madd(10, 20) << endl;//仿函数和普通函数调用差不多,仿函数就是对‘=’赋值运算符的重载

	cout << myadd()(30, 40) << endl;//匿名函数调用,匿名函数对象创建(使用完一次就释放内存,对象不存在)


}

五、组合和继承

组合:将其他类作为自己的数据成员,调用其接口,但是无法添加新的功能
继承:public继承,继承其他类的成员和属性,可以根据成员添加新的功能,也就是创建更加高级的功能。

#include "arr.h"
#include <iostream>

using namespace std;

class ARRX:public ARR{//继承
public:
	int ever(void)//添加求平均功能
	{
		int i = 0;
		int sum = 0;
		for(;i<tail; i++)
			sum += data[i]; 
		return sum/tail;
	}
};

class Stuma{
public:
	Stuma(){

	}
	~Stuma() { }
	
	void savescore(int score)
	{
		scorearr.addtail(score);
	}
	
	int everscore(void)//组合调用新添加求平均功能
	{
		return scorearr.ever();
	}

	void showscore(void)
	{
		scorearr.show();
	}

private:
	//ARR scorearr;
	ARRX scorearr;//组合
};

int main()
{
	Stuma mmm;

	mmm.savescore(23);
	mmm.savescore(44);
	mmm.savescore(55);
	mmm.savescore(23);

	mmm.showscore();
	cout << mmm.everscore() <<endl;
}

六、多态

虚函数(virtual)

#include<string>
#include<stdio.h>
#include <iostream>
using namespace std;

class A {
public:
	virtual~A() { cout << "A--------" << endl; }
	virtual void show() {//虚函数
		cout << "aaaaaa" << endl;
	}
private:
	int x;
	int y;

};
class AX :public A {
public:
	virtual ~AX() { cout << "AX-----" << endl; }
	void show() {
		cout << "AAAAAAA" << endl;
	}
};


int main() {

	AX a;
	/*c++允许基类指针指向派生类对象*/
	A* p = &a;
	p->show();//没有虚函数请款结果为"aaaaaa",根据指针类型确定。添加虚函数的情况下,结果为:"AAAAAAA"
				//派生类同名函数对基类函数进行了一个完全覆盖
	AX* q = &a;
	q->show(); //没有虚函数请款结果为"AAAAAAA"

	/*虚析构函数*/
	A* x = new AX;
	delete x;		//因为x是A基类指针,因此在释放内存时会导致只调用基类的析构函数,那么派生类的析构没有调用,造成内存的泄露
					//因此在编程当中,养成基类的虚构函数变成纯虚构函数,这样派生类的虚构函数也会调用

}

多态应用(联合动态编程)

编写一个类,可以求多种图形的周长

#include<string>
#include<stdio.h>
#include <iostream>
using namespace std;

class shape {

public:
	virtual double getC(void) {
		return 0;
	}

};
class Cir :public shape {
public:
	Cir(double r) :ri(r) {}
	double getC(void) {
		return 2 * 3.14 * ri;
	}

private:
	double ri;

};
class Tir :public shape {
public:
	Tir(double a, double b, double c) :e1(a), e2(b), e3(c) {}
	double getC(void) {
		return e1 + e2 + e3;
	}


private:
	double e1;
	double e2;
	double e3;

};
class Sqr :public shape {
public:
	Sqr(double e) {
		this->e = e;
	}
	double getC(void) {
		return 4 * e;
	}

private:
	double e;
};
/*构造一个函数实现不同类型的图形周长的计算,并返回总周长*/
double countC(shape* arry[], int num) {
	double sumC;
	for (int i = 0; i < num; i++)
	{
		sumC += arry[i]->getC();
	}
	return sumC;

}

int main() {

	Cir cir(2);
	Tir tir(3, 4, 5);
	Sqr sqr(6);
	//多态的一种应用,基类构建同名函数,便于统一管理和拓展
	shape* arry[] = { &cir,&tir,&sqr };
	cout << countC(arry, 3);

}

七、异常

异常机制

#include<string>
#include<stdio.h>
#include <iostream>
#include<stdlib.h>
#include<exception>
using namespace std;

//异常,类似c语言goto,如果执行出错进行跳转执行
class argexpect :public exception {//继承c++标准的异常处理类
public:
	const char* what() const throw(){
		return "arg err!";
	}


};

int myatoi(const char* str) {
	if (*str < '0' || *str>'9')
		throw argexpect();
	return atoi(str);

}

int main() {
	try {//无异常执行
		int data = myatoi("abcc");
		cout << data;
	}
	catch (argexpect& e) {//出现异常,捕捉异常消息-消息类型 实例
		cout << e.what();
	}
	

}

强制类型转换

#include<string>
#include<stdio.h>
#include <iostream>
#include<stdlib.h>
#include<exception>
using namespace std;

/*
强制类型转换:四种方式
reinterpret_cast
const_cast
static_cast
dynamic_cast
*/

class A {
public:
	virtual void show() {
		cout << "AAAAAAAA" << endl;
	}

};
class B :public A {
public:
	void show() {
		cout << "BBBBBBB" << endl;
	}


};
int main(void) {
#if 0
	int a;
	char* p = reinterpret_cast<char*>(&a);
	//强制转换为char*类型,但是会有内存泄露的风险
#endif

#if 0
	const int a = 1000;
	int* p = const_cast<int*>(&a);
	//用于const之间的强制转换,也会存在内存泄露风险

#endif // 0

#if 0
	A a;
	B &p = static_cast<B&>(a);
	//用于继承之间的强制转换,但是派生类指向基类会有风险

#endif // 0
#if 1
	try
	{
		A a;
		B& p = dynamic_cast<B&>(a);
		//动态强转提供检测机制,判断强转是否出现异常,使用这个强转类中必须要有虚函数
	}
	catch (const std::exception& e)
	{
		cout << e.what();
	}

#endif // 1




}

自定义转换

#include<string>
#include<stdio.h>
#include <iostream>
#include<stdlib.h>
#include<exception>
using namespace std;

/*自定义转换函数*/
class mytime {
public:
	mytime(int a, int b, int c) :hour(a),min(b),sec(c){}

	operator int() {//强制将时间转化为秒数
		return sec + min * 60 + hour * 60 * 60;
	}
private:
	int hour;
	int min;
	int sec;



};
int main() {
	mytime t(1,2,3);
	int sec = int(t);
	cout << sec;

}

八、模版

函数模版

#include<string>
#include<stdio.h>
#include <iostream>
#include<stdlib.h>
#include<exception>
using namespace std;

//函数模版

template<typename T>
void myswap(T& a, T& b) {
	T temp=a;
	a = b;
	b = temp;
	cout << a << " " << b << endl;
}
void test(void) {
	int a = 10, b = 20;
	//1.自动推导类型
	myswap(a, b);
	//2.显示声明类型
	myswap<int>(a, b);
}
int main() {
	
	
	test();

}

函数模版实现选择排序

#include<string>
#include<stdio.h>
#include <iostream>
#include<stdlib.h>
#include<exception>
using namespace std;


template<class T>
void myswap(T& a, T& b) {
	T temp=a;
	a = b;
	b = temp;

}
//函数模版实现选择排序
template<class T>
void mysort(T a[], int len) {
	
	for (int i = 0; i < len; i++)
	{
		int max = i;
		for (int j = i+1; j < len ; j++) {
			if (a[max] < a[j])max = j;
		}
		if (max != i) {
			myswap(a[i], a[max]);
		}
	}
	for (int i = 0; i < len; i++)
	{
		cout << a[i] << " ";
	}
}

void test(void) {
	int arry[] = { 1,4,5,2,6,12,74,8,9,34 };
	int num = sizeof(arry)/sizeof(int);
	mysort(arry, num);
}
int main() {
	
	
	test();

}

notes:
1、普通函数能欧实现隐式类型转换
2.、函数模版 自动类型推导无法实现隐式类型转换
3、函数模版 显式申明可以实现隐式类型转换(建议使用这种)
4.普通函数和函数模版都可以调用时,优先调用普通函数
5.空模版参数列表可以强制调用函数模版
6.函数模版也可以发生函数重载
7.如果函数模版产生更好的匹配,则调用函数模版

函数模版局限

#include<string>
#include<stdio.h>
#include <iostream>
#include<stdlib.h>
#include<exception>
using namespace std;
//函数模版的局限,对于特殊的数据结构无法处理
class persion {
public:
	persion(string name, int age) {
		this->name = name;
		this->age = age;
	}

	string name;
	int age;

};
template<class T>
bool myjudge(T& a, T& b) {
	if (a == b) return true;
	else return false;
}
//对于特殊数据结构进行具体实现
template<>bool myjudge(persion& a, persion& b) {
	if (a.name == b.name && a.age == b.age)return true;
	else return false;

}

void test(void) {
	persion p1("zhangsan", 10);
	persion p2("lisi", 25);
	cout<<myjudge(p1, p2);

}
int main() {
	
	test();


}

notes:学习使用别人封装好的模版才是重点

类模版

#include<string>
#include<stdio.h>
#include <iostream>
#include<stdlib.h>
#include<exception>
using namespace std;
//函数模版的局限,对于特殊的数据结构无法处理
template<class NameType,class AgeType=int>
class persion {
public:
	persion(NameType name, AgeType age) {
		this->name = name;
		this->age = age;
	}
	void show(void) {
		cout << name << " " << age << endl;
	}
	NameType name;
	AgeType age;


};



void test(void) {
	persion<string>p1("zhangsan", 112);//类模版只能是显式申明调用,而不能像函数模版一样采用自动推导
	
}
int main() {
	
	test();


}

类模版中的成员函数只有在调用阶段才创建

类模版对象做函数参数

#include<string>
#include<stdio.h>
#include <iostream>
#include<stdlib.h>
#include<exception>
using namespace std;
//函数模版的局限,对于特殊的数据结构无法处理
template<class NameType,class AgeType>
class persion {
public:
	persion(NameType name, AgeType age) {
		this->name = name;
		this->age = age;
	}
	void show(void) {
		cout << name << " " << age << endl;
	}
	NameType name;
	AgeType age;


};

//指定传入类型(一般采用这种方式)
void printPersion(persion<string, int>& p) {
	p.show();
}
void test1(void) {
	persion<string,int>p1("zhangsan", 112);//类模版只能是显式申明调用,而不能像函数模版一样采用自动推导
	printPersion(p1);
}
//参数模版化
template<class T1,class T2>
void printPersion1(persion<T1, T2>& p) {
	p.show();
	cout << "T1 type" << typeid(T1).name << endl;
}
void test2(void) {
	persion<string, int>p("lisi", 67);
	printPersion1(p);
}
//整个类模版化
template<class T>
void printPersion3(T& p) {
	p.show();
	cout << "T type:" << typeid(T).name << endl;
}
void test3(void) {
	persion<string, int>p("wanger", 98);
	printPersion3(p);
}

int main() {
	
	test1();
	test2();
	test3();


}

类模版与继承

#include<string>
#include<stdio.h>
#include <iostream>
#include<stdlib.h>
#include<exception>
using namespace std;


/*类模版与继承:子类继承父类必须要指明父类的模版参数类型*/

template<class T>
class Base {
public:
	T m;
};

class Son :public Base<int> {//必须指明父类T的类型


};
//如果想要灵活指定父类T的类型,子类也需要是变类模版
template<class T1,class T2>
class Son2 :public Base<T1> {
public:
	Son2() {
		cout << "T1  type:" << typeid(T1).name() << endl;
		cout << "T2  type:" << typeid(T2).name() << endl;

	}
	T2 x;
};

void test(void) {
	Son2<string, int>s;

}
int main() {
	test();


}

类模版成员函数类外实现

#include<string>
#include<stdio.h>
#include <iostream>
#include<stdlib.h>
#include<exception>
using namespace std;


/*类模版与继承:子类继承父类必须要指明父类的模版参数类型*/
template<class T1,class T2>
class persion {
public:
	persion(T1 name, T2 age);
	void show();

	T1 m_name;
	T2 m_age;

};


template <class T1,class T2>
persion<T1,T2>::persion(T1 name, T2 age) {
	this->m_age = age;
	this->m_name = name;
}


template<class T1,class T2>
void persion<T1, T2>::show(void) {
	cout << "name:" << this->m_name << "age:" << this->m_age << endl;
}



void test(void) {
	persion<string, int>p("zhansgan", 45);

}
int main() {
	test();


}

类模版分文件编写

#include<string>
#include<stdio.h>
#include <iostream>
#include<stdlib.h>
#include<exception>
using namespace std;

#include"persion.hpp"//类模版分文件编写解决:将.h和.cpp的文件写到一个文件,并以.hpp后缀命名


//template<class T1,class T2>
//class persion {
//public:
//	persion(T1 name, T2 age);
//	void show();
//
//	T1 m_name;
//	T2 m_age;
//
//};
//
//
//template <class T1,class T2>
//persion<T1,T2>::persion(T1 name, T2 age) {
//	this->m_age = age;
//	this->m_name = name;
//}
//
//
//template<class T1,class T2>
//void persion<T1, T2>::show(void) {
//	cout << "name:" << this->m_name << "age:" << this->m_age << endl;
//}



void test(void) {
	persion<string, int>p("zhansgan", 45);

}
int main() {
	test();


}

类模版与友元(全局函数类外实现)

#include<string>
#include<stdio.h>
#include <iostream>
#include<stdlib.h>
#include<exception>
using namespace std;

//全局函数类外实现
//首先让编译器知道有个类模版
template<class t1,class t2>
class persion;

//第二,编译器知道全局函数的实现
template<class t1,class t2>
void printPersion2(persion<t1, t2>p) {
	cout << p.m_name<<" "<<p.m_age;
}




template<class t1,class t2>
class persion {

	friend void printPersion1(persion<t1, t2>p) {//全局函数类内实现
		cout << "name:"<<p.m_name << "age:"<<p.m_age;
	}
	friend void printPersion2<>(persion<t1, t2>p);//注意这里需要添加模版空列表参数
public:
	persion(t1 name, t2 age) {
		this->m_age = age;
		this->m_name = name;
	}
private:
	t1 m_name;
	t2 m_age;

};



void test(void) {
	persion<string, int>p("zhansgan", 45);
	//printPersion1(p);
	printPersion2(p);
}
int main() {
	test();


}

九、STL标准模版库

容器 算法 迭代器

预备知识

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

void printfNum(int val) {

	cout << val << " ";
}

int main() {

	vector<int>num;
	for (int i = 0; i < 10; i++)
	{
		num.push_back(i);
	}

	for (vector<int>::iterator it = num.begin(); it < num.end(); it++)//*it就代表<>中的内容,这里*it代表int
	{
		cout << *it << " ";
	}
	cout << endl;

	for_each(num.begin(), num.end(), printfNum);//利用算法遍历

	vector<vector<int>>nums;//容器嵌套
	for ( int i = 0;  i < 10;  i++)
	{
		nums.push_back({ i,i + 1,i + 2 });
	}

	for (vector<vector<int>>::iterator  it = nums.begin(); it <nums.end() ; it++)
	{

		for (vector<int>::iterator its = (*it).begin(); its < (*it).end(); its++)
		{
			cout << *its << " " ;
		}
		cout << endl;
	}
	

}


1.string

2.vector

互换容器->swap(vec)

3.deque

双端数组,可以对头端也可以对尾端进行插入和删除的操作

4.stack

5.queue

6.list

7.set

8.pari

9.set

10.map

十、常用算法

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值