1.命名空间:类似于Java中包
标准命名空间:standard(包含很多标准的定义)
使用 using namespace std;
自定义命名空间:
namespace NSP_A{
int a = 9;
struct Teacher{
char name[20];
int age;
};
struct Student{
char name[20];
int age;
};
}
namespace NSP_B{
int a = 12;
//命名空间嵌套
namespace NSP_C{
int c = 90;
}
}
2.C++的结构体可以加访问权限和C++类写法类似:
struct MyTeacher{
public:
char name[20];
int age;
public:
void say(){
cout << this->age << "岁" << endl;
}
};
#define PI 3.14
//类
class MyCircle{
//属性(共用权限访问修饰符)
private:
double r;
double s;
public:
void setR(double r){
this->r = r;
}
//获取面积
double getS(){
return PI * r * r;
}
};
3.引用:是变量的别名,指向同一个内存空间
主要功能:作为函数的参数或返回值
//1.单纯给变量取别名没有任何意义,作为函数参数传递,能保证参数传递过程中不产生副本
//2.引用可以直接操作变量,指针要通过取值(*p),间接操作变量,指针的可读性差
//常引用类似于java中final
void myprintf(const int &a){
cout << a << endl;
}
指针的引用,代替二级指针//Teacher* &p = (Teacher * *p)
void getTeacher(Teacher* &p){
p = (Teacher*)malloc(sizeof(Teacher));
p->age = 20;
}
void main(){
Teacher *t = NULL;
getTeacher(&t);
}
和指针对比,更方便:
int a = 1,b = 2;
//指针值交换
void swap_1(int *a, int *b){//调用 swap_1(&a,&b)
int c = 0;
c = *a;
*a = *b;
*b = c;
}
//引用值交换
void swap_2(int &a, int &b){//调用 swap_2(a,b)
int c = 0;
c = a;
a = b;
b = c;
}
4.C++类的一般写法:
a.新建.h文件eg,MyTeacher.h
#pragma once //保证这个头文件只被编译一次
class MyTeacher{
public:
int age;
char* name;
public:
void setAge(int age);
int getAge();
void setName(char* name);
char* getName();
};
b.新建MyTeacher.cpp
#include "MyTeacher.h"
void MyTeacher::setAge(int age){
this->age = age;
}
int MyTeacher::getAge(){
return this->age;
}
void MyTeacher::setName(char* name){
this->name = name;
}
char* MyTeacher::getName(){
return this->name;
}
c.在需要用到MyTeacher类的地方引入头文件即可
5.构造函数
class Teacher{
private:
char *name;
int age;
public:
//无参构造函数(写了,就会覆盖默认的无参构造函数)
Teacher(){
cout << "无参构造函数" << endl;
}
//有参构造函数会覆盖默认的构造函数
Teacher(char *name, int age){
this->name = name;
this->age = age;
cout << "有参构造函数" << endl;
}
};
void main(){
//Teacher t1;
Teacher t2("yuehan",20);
//另外一种调用方式
Teacher t3 = Teacher("jack",21);
}
6.析构函数
class Teacher{
private:
char *name;
int age;
public:
//无参构造函数赋默认值
Teacher(){
this->name = (char*)malloc(100);
strcpy(name,"jack walson");
age = 20;
cout << "无参构造函数" << endl;
}
//析构函数
//当对象要被系统释放时,析构函数被调用
//作用:善后处理
~Teacher(){
cout << "析构" << endl;
//释放内存
free(this->name);
}
};
7.拷贝构造函数
class Teacher{
private:
char *name;
int age;
public:
Teacher(char *name, int age){
this->name = name;
this->age = age;
cout << "有参构造函数" << endl;
}
//拷贝构造函数(值拷贝)
//默认拷贝构造函数,就是值拷贝
Teacher(const Teacher &obj){
this->name = obj.name;
this->age = obj.age;
cout << "拷贝构造函数" << endl;
}
void myprint(){
cout << name << "," << age << endl;
}
};
Teacher func1(Teacher t){
t.myprint();
return t;
}
void func2(Teacher t){
t.myprint();
}
void main(){
Teacher t1("rose",20);
//拷贝构造函数被调用的场景
Teacher t2 = t1;//1.声明时赋值
func2(t1);//2.作为参数传入,实参给形参赋值
Teacher t3 = func1(t1); //3.作为函数返回值返回,给变量初始化赋值,
// 注意这里会调用两次拷贝构造函数:1次是因为作为参数传入,第二次是因为作为函数返回值返回
//这里不会被调用
//Teacher t1 ;
//Teacher t2;
//t1 = t2;
}
8.深拷贝与浅拷贝:
a.浅拷贝(值拷贝)问题:只会拷贝一份引用,还是指向同一个内存
class Teacher{
private:
char *name;
int age;
public:
Teacher(char *name, int age){
this->name = (char*)malloc(100);
strcpy(this->name,name);
this->age = age;
cout << "有参构造函数" << endl;
}
~Teacher(){
cout << "析构" << endl;
//释放内存
free(this->name);
}
void myprint(){
cout << name << "," << age << endl;
}
};
void func(){
Teacher t1("rose", 20);
Teacher t2 = t1;
t2.myprint();
}
void main(){
func();//在方法结束的时候,析构函数会调用两次(回收t1和t2时)
//因为这里是浅拷贝,所以name只分配了一块内存,进行第二次析构函数的调用时会出错!解决方法:使用深拷贝
}
b.深拷贝:
class Teacher{
private:
char *name;
int age;
public:
Teacher(char *name, int age){
int len = strlen(name);
this->name = (char*)malloc(len+1);
strcpy(this->name, name);
this->age = age;
cout << "有参构造函数" << endl;
}
~Teacher(){
cout << "析构" << endl;
//释放内存
free(this->name);
}
//深拷贝
Teacher(const Teacher &obj){
//复制name属性
int len = strlen(obj.name);
this->name = (char*)malloc(len+1);
strcpy(this->name,obj.name);
this->age = obj.age;
}
void myprint(){
cout << name << "," << age << endl;
}
};
void func(){
Teacher t1("rose", 20);
Teacher t2 = t1;
t2.myprint();
}
void main(){
func();
}
9.构造函数的属性初始化列表
class Teacher{
private:
char* name;
public:
Teacher(char* name){
this->name = name;
cout << "Teacher有参构造函数" << endl;
}
~Teacher(){
cout << "Teacher析构函数" << endl;
}
char* getName(){
return this->name;
}
};
class Student{
private:
int id;
//属性对象
Teacher t1;
Teacher t2;
public:
Student(int id,char *t1_n, char* t2_n) : t1(t1_n), t2(t2_n){
this->id = id;
cout << "Student有参构造函数" << endl;
}
void myprint(){
cout << id << "," << t1.getName() <<"," << t2.getName() << endl;
}
~Student(){
cout << "Student析构函数" << endl;
}
};
10.类的大小:
方法和静态变量都不计算到类的大小里面去
class B{//大小为12
public:
int i;
int j;
int k;
void myprintf(){
cout << "打印" << endl;
}
static int m;
};
11.常函数(在函数后面 加 const关键字),常函数中当前对象以及对象的成员都不能被修改
12.友元函数
class A{
//友元函数
friend void modify_i(A *p, int a);
private:
int i;
public:
A(int i){
this->i = i;
}
void myprint(){
cout << i << endl;
}
};
//友元函数的实现,在友元函数中可以访问私有的属性
void modify_i(A *p, int a){
p->i = a;
}
13.友元类
class A{
//友元类
friend class B;
private:
int i;
public:
A(int i){
this->i = i;
}
void myprint(){
cout << i << endl;
}
};
class B{
public:
//B这个友元类可以访问A类的任何成员
void accessAny(){
a.i = 30;
}
private:
A a;
};
14.运算符重载
a.外部重载
class Point{
public:
int x;
int y;
public:
Point(int x = 0, int y = 0){
this->x = x;
this->y = y;
}
void myprint(){
cout << x << "," << y << endl;
}
};
//重载+号
Point operator+(Point &p1, Point &p2){
Point tmp(p1.x + p2.x, p1.y + p2.y);
return tmp;
}
//重载-号
Point operator-(Point &p1, Point &p2){
Point tmp(p1.x - p2.x, p1.y - p2.y);
return tmp;
}
b.成员函数,运算符重载
class Point{
public:
int x;
int y;
public:
Point(int x = 0, int y = 0){
this->x = x;
this->y = y;
}
//成员函数,运算符重载
Point operator+(Point &p2){
Point tmp(this->x + p2.x, this->y + p2.y);
return tmp;
}
void myprint(){
cout << x << "," << y << endl;
}
};
Point p1(10, 20);
Point p2(20, 10);
//运算符的重载,本质还是函数调用
//p1.operator+(p2)
Point p3 = p1 + p2;
c.当属性私有时,通过友元函数完成运算符重载
class Point{
friend Point operator+(Point &p1, Point &p2);
private:
int x;
int y;
public:
Point(int x = 0, int y = 0){
this->x = x;
this->y = y;
}
void myprint(){
cout << x << "," << y << endl;
}
};
Point operator+(Point &p1, Point &p2){
Point tmp(p1.x + p2.x, p1.y + p2.y);
return tmp;
}
15.父类构造函数先调用、子类的析构函数先调用
16.多重继承的二义性:多个父类有相同的属性或者函数,子类不知道该调用哪个,解决方法:虚继承(不同路径继承来的同名成员只有一份拷贝,解决不明确的问题)
class A{
public:
char* name;
};
class A1 : virtual public A{
};
class A2 : virtual public A{
};
class B : public A1, public A2{
};
void main(){
B b;
b.name = "jason";
//指定父类显示调用
//b.A1::name = "jason";
//b.A2::name = "jason";
}
17.多态(程序的扩展性)
动态多态:程序运行过程中,觉得哪一个函数被调用(重写)
静态多态:重载
18纯虚函数(抽象类)
virtual void foo1();//虚函数
virtual void foo2() = 0;//纯虚函数
1.当一个类具有一个纯虚函数,这个类就是抽象类
2.抽象类不能实例化对象
3.子类继承抽象类,必须要实现纯虚函数,如果没有,子类也是抽象类
抽象类的作用:为了继承约束,根本不知道未来的实现
19.模板函数
template <typename T>
void myswap(T& a, T& b){
T tmp = 0;
tmp = a;
a = b;
b = tmp;
}
//使用,根据实际类型,自动推导
int a = 10, b = 20;
myswap<int>(a,b);
cout << a << "," << b << endl;
char x = 'v', y = 'w';
myswap(x, y);
cout << x << "," << y << endl;
20.模板类
//模板类
template<class T>
class A{
public:
A(T a){
this->a = a;
}
protected:
T a;
};
//普通类继承模板类
class B : public A<int>{
public:
B(int a,int b) : A<int>(a){
this->b = b;
}
private:
int b;
};
//模板类继承模板类
template <class T>
class C : public A<T>{
public:
C(T c, T a) : A<T>(a){
this->c = c;
}
protected:
T c;
};
void main(){
//实例化模板类对象
//List<String> list;
A<int> a(6);
system("pause");
}
21.异常处理:
a.
void main(){
try{
int age = 300;
if (age > 200){
throw 9.8;
}
}
catch (int a){
cout << "int异常" << endl;
}
catch (char* b){
cout << b << endl;
}
catch (...){
cout << "未知异常" << endl;
}
system("pause");
}
b.throw
void mydiv(int a, int b){
if (b == 0){
throw "除数为零";
}
}
void func(){
try{
mydiv(8, 0);
}
catch (char* a){
throw a;
}
}
void main(){
try{
func();
}
catch (char* a){
cout << a << endl;
}
system("pause");
}
c.抛出对象异常类
class MyException{
};
void mydiv(int a, int b){
if (b == 0){
throw MyException();
//throw new MyException; //不要抛出异常指针
}
}
void main(){
try{
mydiv(8,0);
}
catch (MyException& e2){
cout << "MyException引用" << endl;
}
//会产生对象的副本
//catch (MyException e){
// cout << "MyException" << endl;
//}
catch (MyException* e1){
cout << "MyException指针" << endl;
delete e1;
}
system("pause");
}
d.throw 声明函数会抛出的异常类型
void mydiv(int a, int b) throw (char*, int) {
if (b == 0){
throw "除数为零";
}
}
e.标准异常(类似于JavaNullPointerException)
lass NullPointerException : public exception{
public:
NullPointerException(char* msg) : exception(msg){
}
};
void mydiv(int a, int b){
if (b > 10){
throw out_of_range("超出范围");
}
else if (b == NULL){
throw NullPointerException("为空");
}
else if (b == 0){
throw invalid_argument("参数不合法");
}
}
void main(){
try{
mydiv(8,NULL);
}
catch (out_of_range e1){
cout << e1.what() << endl;
}
catch (NullPointerException& e2){
cout << e2.what() << endl;
}
catch (...){
}
system("pause");
}
f.外部类异常
class Err{
public:
class MyException{
public:MyException(){
}
};
};
void mydiv(int a, int b){
if (b > 10){
throw Err::MyException();
}
}
22.C++类型转换
static_cast 普遍情况
const_cast 去常量
dynamic_cast 子类类型转为父类类型
reinterpret_cast 函数指针转型,不具备移植性
23.IO流
#include <iostream>
#include <fstream>
using namespace std;
//IO流
//文本文件操作
void main(){
char* fname = "c://dest.txt";
//输出流
ofstream fout(fname);
//创建失败
if (fout.bad()){
return;
}
fout << "jack" << endl;
fout << "rose" << endl;
//关闭
fout.close();
//读取
ifstream fin(fname);
if (fin.bad()){
return;
}
char ch;
while (fin.get(ch)){
//输出
cout << ch;
}
fin.close();
}
//二进制文件
void main(){
char* src = "c://src.jpg";
char* dest = "c://dest.jpg";
//输入流
ifstream fin(src, ios::binary);
//输出流
ofstream fout(dest, ios::binary);
if (fin.bad() || fout.bad()){
return;
}
while (!fin.eof()){
//读取
char buff[1024] = {0};
fin.read(buff,1024);
//写入
fout.write(buff,1024);
}
//关闭
fin.close();
fout.close();
}
24.持久化对象
int main()
{
Person p1("柳岩", 22);
Person p2("rose", 18);
//输出流
ofstream fout("c://c_obj.data", ios::binary);
fout.write((char*)(&p1), sizeof(Person)); //指针能够读取到正确的数据,读取内存区的长度
fout.write((char*)(&p2), sizeof(Person));
fout.close();
//输入流
ifstream fin("c://c_obj.data", ios::binary);
Person tmp;
fin.read((char*)(&tmp), sizeof(Person));
tmp.print();
fin.read((char*)(&tmp), sizeof(Person));
tmp.print();
return 0;
}