锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

C++学习笔记

时间:2023-01-19 07:00:00 ha重载矩形连接器

目录

  • A.c 与c的区别
    • 1.头文件
    • 2.数据类型
    • 3.函数思想的转变
    • 4.C 中的引用 int &形参=实参
    • 5.结构体中的结构函数
    • 6.C 的无头链表
    • 7.this指针
  • 2.C 类和对象
    • 1.构造函数和分析函数
    • 2.复制结构函数
    • 3.浅拷贝和深拷贝
    • 4.类的组合
    • const char* str 传参
    • 动态内存分配
    • 静态成员变量
    • 静态成员函数
    • 面向对象
    • 函数指针
      • 知识点
    • 运算符重载
    • 类的继承
    • 控制访问权限
    • 能否被访问&&继承方式的选择
    • 继承的兼容性
    • 多继承
    • 多态性和virtual
    • IO流
    • C常用英语单词
    • 标准输入流
    • 文件IO
    • 异常处理
      • 问题
      • 小项目 数组类 成员调用
      • 小问题 内存窗口终于打开了
    • 加油 加油 加油啊
    • 模板
      • 总结
      • 类的相加重载
    • C 11 14 标准
    • auto 和 decltype推导类型
    • 后置返回类型
    • 别名
    • lambda 匿名函数
    • STL模板库
    • STL 之string一些容器指令
    • vector容器
    • deque
    • list容器
    • queue容器
    • set容器
    • pair
    • 仿函数
    • map容器
    • multimap 案例
    • STL容器共性机制
    • STL部分算法
    • 适配器
      • 声明和 定义只能保留一个地方的默认参数

A.c 与c的区别

1.头文件

在这里插入图片描述
标准库变为
#include
#include 也可以正常引入
#include 前面加上c 后面去掉.h 也是可以的
//1.头文件发生变化
#include
#include
#include

//2.定义命名空间
using namespace std;
namespace 厨房
{
int k = 99;
}
//3.命名空间的嵌套
namespace a
{
int j = 9;
namespace b
{
int h = 9;
}
}
int main()
{///空间写在函数外,全局变量
///访问空间中的值 空间::成员
//作用域分辨率 ::
printf("%d\n",厨房::k);
//但是太麻烦了
///引入以去除前缀using
using namespace 厨房//功能是去掉 std::
printf("%d\n", k);

//嵌套 printf("%d",a::b::h); using namespace a::b; printf("%d", h);   return 0; 

}

2.数据类型

一个汉字是两个字节
定义函数的时候,记得加括号

#include
#include
#include//c 中间字符串处理
#include//c语言中的字符串处理
using namespace std;///这句话一定要加,因为cin cout在这个命名空间里
struct girl
{ //数据成员:属性
char name[20];
int age;
//成员函数:行为
void print()
{
cout << name << " " << age << endl;
}

};
int main()
{
bool boolNum = 1;
//bool类型
//1.含义:真假
//2.打印值:0和1
//3.功能返回值
//4.特殊的初始化
//5.非零表示成立,-1也表示成立,0表示不成立
boolNum =true;
boolNum = false;
boolNum = -1;
printf("%d\n", boolNum);
///指针赋值变化 NULL->nullptr
int *ptr = nullptr;
///动态申请内存 malloc free-》new delete
//1.分配单个内存,指针变成普通变量
ptr = new int;
//2.分配一段内存
int *array = new int[10];// int array[10]
//3.申请内存并且初始化
int *a = new int(12)
int *pArray = new int[10]{1, 2, 3}//数组指针大括号初始化
printf("%d\n", *(pArray 4));
优化出现在这里。c语言在申请内存时不能初始化

delete a; delete pArray; delete[] array;///释放数组 delete ptr;//释放普通变量 //4.内存池,申请的内存可以分配 char *malloc = new char[1024] int *ray = new(malloc) int;//前面malloc 代表首地址 int 代表申请四个字节 char *pStr = new(malloc   4) char[100] 类型 *指针名=new[] delete[] malloc;///直接释放总内存 //输入输出 //输出 printf---> cout<< //输入 scanf----> cin>> //1.单个数据的输入和输出 int num = 0;///初始化还是一样的 char str[20] = "";//字符串 ///不需要格式控制字符,变得简洁 printf("请输入一个num:"); cin>> num; cout << num; printf("请输入字符串str;"); cin >> str; cout << str<"\n"多一个功能,清空缓冲区 cout << "i love you" << "\t" << num << str << endl; cin >> num >> str; cout << num << str; //4,结构体 //1.函数可以存在于内部 //2.不需要使用结构类型struct girl Mygirl = { "baby", 100 }; //3.概念性的东西,属性,行为 //4.访问函数与访问结构成员的行为相同 Mygirl.print();//访问函数 //string的基本使用 //string不是C语言中的字符串 //1基本创建
string str0;
string str1("hua");
string str2 = "huaewf";
string str3(str1);//也可以串变量和常量
//基本操作
string str5= str1 + str2;
cout << (str5> str2) << endl;
cout << (str5== str2) << endl;
cout << (str5< str2) << endl;
//C++中的string转换为c语言中的字符串;
printf("%s\n", str5);//输出乱码,因为c++中的string不是字符串
printf("%s\n", str5.c_str());//c_str()返回字符串首地址

system("pause");
return 0;

}

3.函数思想转变

#include
using namespace std;
/*
内敛函数:二进制代码形式存在,牺牲空间,提高效率 短小
inline 或者在结构体中 或者 在类中实现的函数

函数重载:允许同名不同参函数存在
三个不同参:
数目不同
类型不同
顺序不同

函数缺省:即给参数初始化 重载的集合体
注意问题:从右往左不能留空

*/
inline int Max(int a, int b)
{
return a > b ? a : b;
}
//数目不同
int Max(int a, int b, int c)
{
return a + b + c;
}
//类型不同
char Max(char a, char b)
{
return a > b ? a : b;
}
//顺序不同,一定有不同类型
void print(char a, int b)
{
cout << a << " " << b< }
void print(int a, char b)
{
cout << a << " " << b;
}
//函数缺省 从右往左
void function(int a, int b = 3, int c = 4)
{
cout << a + b + c << endl;
}
int main()
{
print(‘A’, 12);
print(12, ‘A’);
//没有注明是几,则使用默认值
//缺省能够实现同一函数的不同调用形式
function(1);
function(2, 3, 4);

system("pause");
return 0;

}

4.C++中的引用 int &形参=实参

#include
using namespace std;
void Modify(int *a)
{
*a = 100;

}
void modify(int &num)
{
num = 12;
}
//输入常数的两种方法
void print(const int &nam)
{//const 不能改变形参的值
cout << nam << endl;
}
void Print(int &&nam)
{
cout << nam << endl;

}
struct girl
{
char name[20];
int age;
int getAge()
{
return age;
}

};
//不能返回局部变量
int get()
{
int num;
return num;//因为局部变量会在使用后释放内存,无法返回
}
int main()
{//引用 &
//起别名
int num = 0;
int &sf = num;//int &形参=实参 则&形参=实参
sf = 2;//sf 和num指向同一空间 ,修改sf就等于修改num
cout << num << endl;
//用在哪里呢
//1.当需函数的返回,防止拷贝本的产生,真正改变实参
//在C语言中,使用指针改变实参
//c++中,使用引用来改变
int d = 8;
modify(d);
cout << d << endl;
/*int *d = 8;
Modify(d);/
//modify(1)会出错 int &形参=实参; 形参必须是标识符
//想要输出常数
print(2);
Print(2);
//2.当做函数返回,返回一个变量,增加左值使用
girl myGirl = { “花花”, 20 };
myGirl.age = 18;
cout << myGirl.age << " " <

/*int k= get();
cout << k << endl;*/// 错误用法

system("pause");
return 0;

}

5.结构体中的构造函数

#include
#include
using namespace std;
//面向对象的方式写一个链表
//c++特殊的函数:构造函数
// 1.名字和结构体名称相同;
// 2.没有返回值
// 3.结构体变量被创建的时候调用;
struct MM
{
string name;
int age;
//构造函数 作用:为基本数据成员初始化
MM(string nameM, int ageM)//这里以后会讲 不能写成跟原来一样
{
name = nameM;
age = ageM;
cout << “调用构造函数的过程” << endl;
}
void print()
{
cout << name << " " << age << endl;
}
};
void print(struct MM mm)
{
cout << mm.name << " " <

}
int main()
{//构造函数决定了结构体变量的类型
MM mm = { “花花”, 12 };
MM mm2(“憨憨”, 13);//c++初始化采用调用函数的过程
//C++面向对象的方式,
//行为是描述对象的
mm.print();//C++先创建对象,然后调用行为
//C语言一般是面向过程,都是行为操控对象
print(mm);//c语言行为调用对象

return 0;

}

6.C++的无头链表

#include
using namespace std;
/*
无头链表
/
struct Node
{
int data;
struct Node
next;
Node()
{
next = nullptr;
}
Node(int dataA)
{
data = dataA;
}
Node(int dataA,Node* nextA)
{
data = dataA;
next = nextA;
}
};
struct list
{
Node* froNode;//不加struct
int size;
list();//构造函数
void insertBt(int data);
void printList();
};
//在结构体外面定义函数
list::list()
{
froNode = NULL;
size = 0;

}
void list::insertBt(int data)
{
froNode = new Node(data, froNode);//new 一个结构体//连接操作
//用一个构造函数就封装好了连接
/*1.next指向nextA,即froNode,即Null;
2.然后froNode又指向新创建的这个节点的首地址
*/

}
void list::printList()
{
Node* pMove = froNode;//粗心大意了,应该是不为空时
while (pMove)
{
cout << pMove->data << endl;
pMove = pMove->next;
}
}
int main()
{
list* pList = new list; //不懂
pList->insertBt(1);
pList->insertBt(1);
pList->insertBt(1);
pList->printList();

return 0;

}

7.this指针

#include
#include
using namespace std;
struct girl
{
string name;
int age;
girl(string name, int age)
{//当形参的名字和实参的名字相同时
this->name = name;
this->age = age;
}
girl getGirl()这里也不懂
{
return *(this);//返回这个类
}
void print()
{
cout << name << " " << age << endl;
}
};
int main()
{
girl *pGirl = new girl(“花花”, 12);
cout << pGirl->getGirl().getGirl().getGirl().age< //符合语法,实质是对自身进行递归

system("pause");
return 0;

}

2.C++类和对象

新学习到的知识:
char * str= “Hello World”;字符指针
char str[ ]=“Hello World”;字符数组
都可以储存字符串
char str= ‘ A’;字符
——————————————————————

#include
#include
using namespace std;
class person
{
//1.class和struct都可以定义类
//struct 默认公有
//class 默认私有
//2.private,public,protected
//3.在类的外面实现成员函数定义 作用域分辨符:: 函数名前加
private://在类的外部不能调用内部
public:
//行为 吃饭
void eat()
{
cout << “吃饭” << endl;
}
void drink()
{
cout << “喝水” << endl;
}
int person::getAge()
{
return age;//private可以内部访问,但是不能外部访问
}
const char* getName();

	/*void set(int ageA,string nameA)
	{
	age = ageA;
	name = nameA;
	}*/
	person(int age = 3, string name = "花花")
{
	this->age = age;
	this->name = name;
}


//属性

private://属性设置为公有不安全,任何对象都能访问
//所以一般设置为私有
int age;
string name;
//protected:保护的,在类的继承中起作用
};

const char* person::getName()
{
return name.data();//完全不懂
}
int main()
{
person 黄
飞鸿(2,“花花”);

黄飞鸿.eat();
cout << 黄飞鸿.getAge() << " " << 黄飞鸿.getName() << endl;
cout << sizeof(string) << endl;
cout << sizeof(person) << endl;

return 0;

}
———————————————————————————————
#include

using namespace std;
#define MAX(a,b)((a)> (b) ? (a) : (b))
inline int max(int a, int b)//加了inline就不用挑了
{
return a > b ? a : b;//函数这种就需要跳出来运行 ,在跳回去
}
//内联函数 使用关键字 inline 放在返回值类型前面
//1.可以用来替换宏函数,在编译期间,直接替换到调用处
//2.减少开销 不用跳
int main()
{//比较两个数的大小
int a = 4, b = 9;
int mmax = max(a, b);

return 0;

}

1.构造函数和析构函数

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
using namespace std;
class Stu
{
public:
/*构造函数和析构函数同级调用顺序:
和栈一样:(一个碗) 构造函数:先来先调用 -->入栈
析构函数: 后来先调用—>出栈

*/
//构造函数,函数名和类名相同  没有返回类型
//类型:
//1.无参构造(默认构造)
//2.有参构造
//3.拷贝构造

Stu()
{
	m_age = 10;
	name=(char*)malloc(sizeof(char)* 13);//动态申请内存
	strcpy(name, "NUL");
	cout << "我是构造函数" << endl;

}
//重载函数 重名
Stu(int tage,  char* tname)
{
	m_age=tage ;
	name = (char*)malloc(strlen(tname)+1);//确切的空间大小 记得加\0这个1
	//这里要注意 malloc里面要写大小 ,那么里面也可sizeof(char)*strlen(tname)+1
	strcpy(name, tname);
	cout << "我是构造函数" << endl;
}
//析构函数 释放内存
//没有参数 也没有任何返回类型
//在主函数完成后自动调用
~Stu()
{
	if (name != NULL)
	{
		free(name);
		name = NULL;
	}
	cout << "我是析构函数" << endl;
}

int getAge()
{
	return m_age;
}
char* getName()
{
	return name;
}

private:
int m_age;
char* name;
};
int main()
{

Stu maye;//无参构造函数,不需要写括号
cout << maye.getName() << " " << maye.getAge() << endl;
//有参构造调用方法
//1.直接在对象后面
Stu newy(28, “慕容”);
cout << newy.getName() << " " << newy.getAge() << endl;
//2.创建列表
Stu cc = { 56, “画画” };
cout << cc.getName() << " " << cc.getAge() << endl;
//3.通过匿名对象初始化
Stu(34, “哗哗”);//无名创建 如果没有接 执行完构造函数,立即执行析构函数
//生命周期取决于如何处理(如何后接)
//如果用有名对象去接,他就会直接转正,不会立马释放,当有名对象生命周期结束,才会释放(正常了)

Stu xoy = Stu(28, "佐助");
cout << xoy.getName() << " " << xoy.getAge() << endl;
//浅拷贝
//编译器自己实现的是浅拷贝,我们自己实现深拷贝
//Stu 成毅(30, "司凤");
//Stu 司凤 = 成毅;//把成毅拷贝给了司凤
//成毅.setName("花花");
//cout << 成毅.getName() << endl;
//cout << 司凤.getName() << endl;










cout << "我是分隔符" << endl;
return 0;
//返回0之后析构

}

2.拷贝构造函数

#include
using namespace std;
class aaa
{
public:
aaa()
{
a = 0;
}
aaa(int a)
{
this->a = a;
}
//如何自己去写拷贝构造函数
aaa(aaa& other)//加& 不报错 为啥 只能长这个样子
{
a = other.getA();

}

int getA()
{
	return a;
}

private:
int a;
};
int main()
{
aaa tt;
cout << tt.getA() << endl;
aaa t(2);
cout << t.getA() << endl;//如果没有写构造函数,会自动生成一个构造函数返回乱码
//用一个对象去初始化另一个对象,需要拷贝构造函数
//如果没有写拷贝构造函数,编译器会自动给我们一个拷贝构造函数
//1.
aaa t1 = t;//初始化
cout << t1. getA() << endl;
//2.
aaa t2(t);
cout << t2.getA() << endl;
//无名对象初始化 会调用拷贝构造函数吗? 不会调用
aaa t3 = aaa(23);//无名对象直接转正,获得姓名t3
cout << t3.getA() << endl;

aaa 新建;
新建 = t;  //赋值  //这里需要拷贝构造函数吗? 不需要,所需为运算符重载=
//初始化和赋值是不一样的
//初始化:在定义的同时赋值
//赋值:在初始化后赋值


return 0;

}

3.浅拷贝和深拷贝


1.浅拷贝知识拷贝类,但没有拷贝空间,指针指向同一区域,在释放内存时,出现问题中断,前面都放掉了,下一个无法释放、

4.类的组合


class A
{
public:
A()
{
}
A(int
a)
{
m_a = a;
}

int getA()
{
	return m_a;
}

//private:
int m_a;
};
class B
{
public:
B(int b, A other)
{
m_b = b;
//m_ba = other;//不是初始化的方式 我们还没有接触到等号重载
}

//private:
int m_b;
A m_ba;
};
对应:B b(20, A(30));

class A
{
public:

A(int a)
{
	m_a = a;
}

int getA()
{
	return m_a;
}

//private:
int m_a;
};
class B
{
public: //我们并不需要默认,但他就是报错,怎么办
B(int b, int a) :m_ba(a) //组合类,这样做就可以了
{
m_b = b;
//m_ba = other;//不是初始化的方式 我们还没有接触到等号重载
}
//private:
int m_b;
A m_ba;
};
对应:B b(20, 30);

#include
using namespace std;
class A
{
public:

A(int a)
{
	m_a = a;
}
~A()
{
	cout << "A的析构函数" << endl;
}

int getA()
{
	return m_a;
}

//private:
int m_a;
};
class B
{
public://我们并不需要默认,但他就是报错,怎么办?
B(int b, int a,int ta) :m_ba(a),maye(ta) //组合类,使用参数列表
{//使用参数列表的两种情况:
//1.别的类
//2.const 属性
// maye = ta;//错误,因为不能对常量进行赋值
m_b = b;
//m_ba = other;//不是初始化的方式 我们还没有接触到等号重载
}
~B()
{
cout << “B的析构函数” << endl;
}
//private:
const int maye;
int m_b;
A m_ba;

};
int main()
{
B b(20, 30,56);
cout << b.m_b << " " << b.m_ba.m_a < //思考:先执行谁的构造函数,是本类还是组合类?
//结论:先执行组合类的,然后执行本类
//先执行谁的析构函数? 跟构造函数相反 先执行本类 在执行组合类

//如果有多个类组合,先定义的先执行构造,后定义的后执行构造,与参数顺序无关



return 0;

}

const char* str 传参



#include
#include
using namespace std;
class My
{
public:
/My(int size = 0) :size(size)
{
c_str = (char
)malloc(size + 1);
strcpy(c_str, “”);
}*/
My()
{

}
My(int size,char* str)
{
	this->size = size;
	strcpy(c_str, str);//字符串的比较和赋值都需要用函数
}
//深拷贝
My(const char* str)
{
	size = strlen(str);
	c_str = (char*)malloc(size + 1);
	strcpy(c_str, str);

}
//拷贝构造 固定模式
My(const My& other)
{
	size = other.size;
	c_str = (char*)malloc(size + 1);
	strcpy(c_str, other.c_str);
}
~My()
{
	if (c_str != NULL)
	{
		free(c_str);
		
	}
}
//设置字符串
void setStr( char* str)
{
	strcpy(c_str, str);
}
//连接
char *mycat(const My& other)
{
	//要考虑,连接进去的内存是否足够
	if (other.size == 0)
	{
		return c_str;
	}
	else
	{
		//先定义一个临时变量来储存字符串
		char* temp = (char*)malloc(size + 1);
		strcpy(temp, c_str);
		free(c_str);

	    c_str = (char*)malloc(size + other.size + 1);
		strcpy(c_str, temp);
		strcat(c_str, other.c_str);
		
		
		free(temp);//释放临时变量


	}
	return c_str;
}
//重载
char *mycat(const char* str)
{
	//要考虑,连接进去的内存是否足够
	if (strlen(str) == 0)
	{
		cout << "啥也没呀" << endl;
	}
	else
	{
		//先定义一个临时变量来储存字符串
		char* temp = (char*)malloc(strlen(str) + 1);
		strcpy(temp, str);
		free(c_str);

		c_str = (char*)malloc(strlen(str)+ 1);
		strcpy(c_str, temp);
		

		free(temp);//释放临时变量

	}
	return c_str;
}
//拷贝
char *mycopy(const char* strr)
{
	strcpy(c_str, strr);
	return c_str;
	
}
//比较
int mycmp(const My& other)
{
	return strcmp(c_str, other.c_str);
}
//翻转
const char* reverse()
{
	for (int i = 0; i < size/2; i++)//注意这里一定要只弄一半 因为否则换后半部分又换换回来了
	{

		char ch = c_str[i];//每次先保存这个字符
		c_str[i] = c_str[size - i - 1];
		c_str[size - i - 1] = ch;
		
	}
	return c_str;
}
//获取字符串
const char* str()
{
	return c_str;
}

private:
int size;
char* c_str;
};
int main()
{
My Mystr(“环环”);
/My Mystr = new My;*/

cout << Mystr.str() << endl;
Mystr.setStr("花花");
My t = Mystr; //如果你不自己构造深拷贝,编译器会自动执行浅拷贝,则字符串指针指向同一空间,析构时出现bug。
cout << t.str() << endl;
/*char* a = "huahua";
char* b = "HUAU";
cout << strcat(a, b) << endl;*/
My sg("欢欢");
sg.mycat(Mystr);
cout <

}

动态内存分配

#include
using namespace std;
class MyClass
{
public:
MyClass(int maye = 22) :maye(maye)
{

}

int getNum()
{
	return maye;
}
~MyClass()
{
	cout << "我是析构函数" << endl;
}

private:
int maye;

};

int main()
{ //申请普通变量
int *pi = new int;
*pi = 520;
cout << *pi << endl;
delete pi;

	//申请的同时初始化
	int *pii = new int(520);		
	cout << *pii << endl;
	delete pii;

	//申请数组 一段内存
	int *arr = new int[10]{1,23,4,5};//2. 大括号初始化 但这种方式只能用于基础数据类型 对象的数组会有问题
	for (int i = 0; i < 10; i++)
	{
		//  *(arr + i) = i;//1.指针赋值方式
		cout << arr[i] <<" ";
	}
	//delete arr;//不对
	delete[] arr;//释放数组 要加中括号

	//new 对象 会自动调用构造函数
	MyClass *pm = new MyClass(33);
	cout << pm->getNum() << endl;
	delete pm;//释放会直接调用类的析构函数

	//输出乱码 malloc仅仅开辟了空间,但没有调用构造函数,free也不调用析构函数
	//所以在c++中,我们常用new/delete来代替malloc/free,在类的使用中更是尤其
	MyClass *pp = (MyClass*)malloc(sizeof(MyClass));
	cout << pp->getNum() << endl;
	free(pp);
	//注意:只有数组在释放时,使用【】
return 0;

}

静态成员变量




#include
using namespace std;
class Stu
{
public:
Stu(int age = 10) :age(age)
{
size++;
}
~Stu()
{

}
int getAge()
{
	return age;

}
int getNum()
{
	return size;
}
static int size;//班级人数

private:
int age;
//这里只是声明静态成员,声明必须在类的里面

};
//初始化类的静态变量,必须在类的外面
int Stu::size = 0;//只用声明的时候加static
//静态变量 一定要初始化 全局变量 不初始化 默认0

int main()
{
Stu VIP优酷[19];//申请数组的时候,每一个对象会自动调用构造函数
cout << VIP优酷[0].getAge() <<" "< //如何统计全班人数,每个人都知道,并且人数是一样的
//班上明明有19个人,为啥只显示1个?每个对象内存空间是独立的,互不影响
//怎么才能让每一个同学共享班级属性? 使用static 静态变量

//两种方式访问静态变量
cout<

}

静态成员函数


#include
using namespace std;
class Stu
{
public:
Stu(int age = 10) :age(age)
{
size++;
}
~Stu()
{

}
int getAge()
{
	return age;

}
static int getNum()//静态函数
{
	//age;//静态函数只能访问静态变量,不能访问普通变量
	return size;
}
static int size;//班级人数

private:
int age;
//这里只是声明静态成员,声明必须在类的里面

};
//初始化类的静态变量,必须在类的外面
int Stu::size = 0;//只用声明的时候加static
//静态变量 一定要初始化 全局变量 不初始化 默认0

int main()
{
Stu VIP优酷[19];//申请数组的时候,每一个对象会自动调用构造函数
cout << VIP优酷[0].getAge() <<" "< //如何统计全班人数,每个人都知道,并且人数是一样的
//班上明明有19个人,为啥只显示1个?每个对象内存空间是独立的,互不影响
//怎么才能让每一个同学共享班级属性? 使用static 静态变量

//两种方式访问静态变量
cout<

}

面向对象







const加的位置不同,不一样

函数指针

#include
using namespace std;
class A
{public:
int j;
int k;
int l;

};
class B
{
public:
int j;
int dd;
int q;
static int h;
};
class Test_m
{

public:
Test_m(int a)
{
m_t = a;
}
//const 加在类型前后 都是修饰返回值
int getT() const //加在函数名后面 修饰的是this指向指向的对象不可修改
{
//this->m_t = 3; this 是一个const指针,指向正在调用的对象,前面自带const
return m_t;
}
Test_m& getThis()
{
return this;
}
static void print()
{
cout << “这是一个测试类” << endl;
}
private:
int m_t;
};
int add(int a, int b)
{
return a + b;
}
//c语言 实现相同功能
struct Test
{
int m_a;
};
void Test_init(Test
const pthis,int a)
{
pthis->m_a = a;
}
int Test_getT(Test* const pthis)
{
return pthis->m_a;
}
void print()
{
cout << “这是一个测试类” << endl;
}

int main()
{
int a = 4;
int b = 2;
add(a, b);//我们会发现面向对象 就是数据和操作(函数)分开声明。
//只有在调用函数时,数据才会和操作有联系。
//对象里面只有数据,没有函数,函数储存在代码段里面。
//而且类没有内存,只是1个类型,对象才有内存
cout << sizeof(A) << endl;
cout << sizeof(B) << endl;//静态变量储存在全局数据 作用域在类里

Test_m AA(3);
AA.getT();
Test_m::print();
printf("_________________________\n");

Test zc;
Test_init(&zc,99);
Test_getT(&zc);
print();
printf("-------------------------\n");

cout << AA.getThis().getThis().getT()<

}

#include
using namespace std;
class MyClass
{
public:
MyClass(int a = 0) :a(a)
{

}
void show()
{
	cout << a << endl;
}
//不管是友元类还是友元函数,都破坏了类的封装性,不建议使用
friend class B;//友元类
//friend void print(MyClass AA);//友元函数 friend前缀声明 访问非公有成员

private:
int a;
};
//void print(MyClass AA)
//{
// AA.a = 456;
// cout << AA.a << endl;
//
//}
class B
{
public:
B(const char* ch)
{
this->ch = new char[strlen(ch) + 1];//重点:指针要存储一串数据就动态申请
strcpy(this->ch, ch);
}
void set(MyClass a)
{
a.a = 888;
aaa.a = 111;
}
char *ch;

MyClass aaa;

};
int main()
{
//MyClass *pp=new MyClass(23);
//pp->show();
///*print(pp);/
//cout << “---------------------”< //MyClass 琉璃(99);
//B 禹司凤(“琉璃”);
//cout << 禹司凤.ch<< endl;
//禹司凤.set(琉璃);
//cout << 禹司凤.ch << endl;

void (MyClass::*pfun)();//函数指针
pfun = &MyClass::show;
//MyClass::show();
//调用函数指针必须要有对象
MyClass zc;
//pfun.show()//x

//(*pfun)();//x
//(MyClass::*pfun)();//x

//函数指针
(zc.*pfun)();//1.

MyClass* pa = new MyClass;//2.
(pa->*pfun)();



return 0;

}

知识点




运算符重载



#include
using namespace std;
//运算符重载其实就是函数
class GirlFriend
{
public:
GirlFriend(int age = 18, int money = 10000) :age(age), money(money){};
int getAge()
{
return age;
}
int gerMoney()
{
return money;
}
void show()
{
cout << age << " " << money << endl;
}
//成员函数
GirlFriend girladd(GirlFriend g2)//其实有两个参数,前面隐藏了this GirlFriend girladd(this,GirlFriend g2)
{

	return GirlFriend(this->age + g2.age, this->money + g2.money);
}
//重载双目 +
GirlFriend operator+ (GirlFriend g2)//其实有两个参数,前面隐藏了this  GirlFriend girladd(this,GirlFriend g2)
{

	return GirlFriend(this->age + g2.age, this->money + g2.money);
}
//比较
bool operator==(GirlFriend g2)
{
	return this->age == g2.age&&this->money == g2.money;
}

private:
friend GirlFriend girladd(GirlFriend g1, GirlFriend g2);
/friend GirlFriend operator+(GirlFriend g1, GirlFriend g2);/
int age;
int money;

};

GirlFriend girladd(GirlFriend g1, GirlFriend g2)
{

return GirlFriend(g1.age + g2.age, g1.money + g2.money);

}
//运算符重载全局函数
//GirlFriend operator+(GirlFriend g1, GirlFriend g2)
//{
//
// return GirlFriend(g1.age + g2.age, g1.money + g2.money);
//}
int main()
{//看来operator+只能弄一个。
//双目操作符重载,
GirlFriend g1, g2;
//GirlFriend g3 = g1.girladd(g2);
//GirlFriend g3 = g1.operator+(g2);
GirlFriend g3 = g1 + g2;
g3.show();
//g1 + g2;
//函数实现
/GirlFriend self=girladd(g1,g2);
cout << self.gerMoney() << " " << self.getAge()</
//运算符重载全局函数
//GirlFriend self = operator+(g1, g2);
GirlFriend self = g1 + g2;
cout << self.gerMoney() << " " << self.getAge() << endl;

cout<

}



#include
using namespace std;
class money
{
public:
money(int rmb = 10000, int dollar = 10000):rmb(rmb),dollar(dollar) {}
money()
{
rmb = 10000;
dollar = 10000;
}

void show()
{
	cout << rmb << "  " <

private:
friend ostream& operator<<(ostream& out, money& m);
friend money operator++(money& m);
friend money operator++(money& m,int);

friend money addMoney(money m);

int rmb;
int dollar;

};

//全局函数
money addMoney(money m)
{//访问私有属性 使用友元函数
m.dollar += 1000;
m.rmb += 1000;
return m;
}
//前缀 前置++
money operator++(money& m)
{//访问私有属性 使用友元函数
m.dollar += 1000;
m.rmb += 1000;
return m;
}
//后置++ 怎么区分前置和后置++ 为了区分 我们可以在后置++的参数里加一个int 标识 不能是其他,也不能传参只是一个标识
money operator++(money& m,int)
{//访问私有属性 使用友元函数
m.dollar += 1000;
m.rmb += 1000;
return m;
}
全局运算符重载函数
ostream& operator<<(ostream& out, money& m)
{
out << m.dollar << " " << m.rmb << endl;
return out;
}
int main()
{

/*money m1, m2;
money m3 = sub(m1, m2);
m3.show();*/

money m1(200, 111);
money m=addMoney(m1);
m.show();
money mm(2,23);
/*money r = operator++(mm);*/
money r = mm++;
mm.show();

//重载<< >>
/*show(cout, mm);*/
//mm << cout;//所以必须这样写,有点奇葩
cout<< mm << endl;
operator<<(cout, mm) << "maye"<

}

类的继承

访问权限控制


能否被访问&&继承方式选择

#include
using namespace std;
class Base//base 基类 老爹
{ 
        public:
	int a;//老爹的名字,大家都知道,都可以用
protected://专门用在继承中
	int b;//家里的钱,只能家里的人用
private:
	int c;//老爹的秘密,只有老爹能用
};

//三种继承方式
//public:常用这个, 能在类的内部访问,也能在类的外部访问
//protected:以私有方式继承,所以的成员都会被继承,但是基类的private不可见,其他的属性都属于子类的私有属性
//private:
class Derive:public Base//继承 儿子
{ 
        
public:
	void setA()
	{ 
        
		a = 12;//在子类的内部,可以被访问
		b = 99;//可以被访问
		//c = 23;//不能被直接访问
		
		cout << a << endl;
	}
protected://专门用在继承中
	
private:
	//相当于a,b都在这里
};
int main()
{ 
        
	Derive der;
	der.setA();
	der.a;//yes
	//der.b;//no 只能在子类中使用
	//der.c;//no 私有



	return 0;
}
#include
using namespace std;
class Base//base 基类 老爹
{ 
        public:
	int a;//老爹的名字,大家都知道,都可以用
protected://专门用在继承中
	int b;//家里的钱,只能家里的人用
private:
	int c;//老爹的秘密,只有老爹能用
};

//三种继承方式
//public:常用这个, 能在类的内部访问,也能在类的外部访问
//protected:以私有方式继承,所以的成员都会被继承,但是基类的private不可见,其他的属性都属于子类的私有属性
//private:
class Derive:public Base//继承 儿子
{ 
        
public:
	void setA()
	{ 
        
		a = 12;//在子类的内部,可以被访问
		b = 99;//可以被访问
		//c = 23;//不能被直接访问
		
		cout << a << endl;
	}
protected://专门用在继承中
	
private:
	//相当于a,b都在这里
};
int main()
{ 
        
	Derive der;
	der.setA();
	der.a;//yes
	//der.b;//no 只能在子类中使用
	//der.c;//no 私有



	return 0;
}

继承的兼容性

#include
#include
using namespace std;
class Parent
{ 
        public:
	int age=12;
	void get爱()
	{ 
        = "司凤";
		cout << "叮咚!你收到了成毅哥哥的爱哦!!" <<<<endl;
	}
protected:
	string 爱;
private:


};
class Child:public Parent 
{ 
        public:
	void show()
	{ 
        
		cout <<<< "爱你爱你" << endl;
	}

};
void print(Parent jj)
{ 
        
	jj.get爱();
}
//子类对象可以当作父类对象使用
//.子类对象可以直接赋值给父类对象
//.子类对象可以直接初始化父类对象
//.父类指针可以直接指向子类对象
//.父类引用可以直接引用子类对象

int main()
{ 
        //.子类对象可以直接初始化父类对象
	Child ch;
	/*ch.get爱();*/
	Parent pa=ch;
	/*cout << pa.age << endl;*/
	pa.get爱();
//需要父类参数的函数,可以直接传子类对象进去
	print(ch);
//.父类指针可以直接指向子类对象
	Parent *pp= &ch;
	pp->get爱();
	//.父类引用可以直接引用子类对象
	Parent& ai = ch;
	ch.show();
	ai.get爱();

	while (1);//system("pause")//防闪退

	return 0;
}


//继承中的构造和析构
#include
using namespace std;
class A
{ 
        
public:
	A(int a, int b)
	{ 
        
		this->a = a;
		this->b = b;
		cout << "父类构造函数" << endl;
	}
	 void showA()
	{ 
        
		 cout << a << " " << b<<endl;
		 
	}
	 ~A()
	 { 
        
		 cout << "父类析构函数" << endl;
	 }
protected:
	int a;
	int b;
private:

};
class B:public A
{ 
        
public:
	B(int aa, int ab, int ac) :/*a(aa),b(ab)*/A(aa, ab), c(ac)//通过初始化参数列表的方式,显示的调用父类的构造函数
	{ 
        
		/*a = aa; b = ab; c = ac;*/
		cout << "子类构造函数" << endl;
	}
	void showB()
	{ 
        
		cout << a << " " << b << " " << c << endl;
	}
	~B()
	{ 
        
		cout << "子类析构" << endl;
	}
protected:
	int c;
private:

};
int main()
{ 
        
	B ha(1, 2, 3);
	ha.showA();
	ha.showB();



	return 0;
}

//继承中的构造和析构
#include
using namespace std;
class A
{ 
        
public:
	A(int a, int b)
	{ 
        
		this->a = a;//这里是赋值,不是初始化
		this->b = b;
		cout << "父类构造函数" << endl;
	}
	 void show()
	{ 
        
		 cout << a << " " << b<<endl;
		 
	}
	 ~A()
	 { 
        
		 cout << "父类析构函数" << endl;
	 }
protected:
	int a;
	int b;
private:

};
class B:public A
{ 
        
public:
	B(int aa, int ab, int ac) :/*a(aa),b(ab)*/A(aa, ab), c(ac)//通过初始化参数列表的方式,显示的调用父类的构造函数
	{ 
        
		/*a = aa; b = ab; c = ac;*/
		cout << "子类构造函数" << endl;
	}
	void show( 

相关文章