由于最近学校开了数据结构,而且是以c++语言来描述,由于本菜鸡转专业并没有接触过c++,特此来补习一下,暂停PHP的学习。
类
简单立方体类设计
#include <iostream>
#include <string>
using namespace std;
class Cube{
private:
int m_L;
int m_H;
int m_W;
public:
//设置长宽高
void set_L(int l)
{
m_L = l;
}
void set_H(int h)
{
m_H = h;
}
void set_W(int w)
{
m_W = w;
}
//获取长宽高
int get_L()
{
return m_L;
}
int get_H()
{
return m_H;
}
int get_W()
{
return m_W;
}
//获取面积
int get_area()
{
return 2 * (m_L * m_W + m_L * m_H + m_H * m_W);
}
//获取体积
int get_volume()
{
return m_W * m_L * m_H;
}
// 成员函数判断两个立方体是否相等
bool isSame(Cube &c1)
{
if(m_H == c1.get_H() && m_W == c1.get_W() && m_L == c1.get_L())
{
return true;
}
else
return false;
}
};
//全局函数判断两个立方体是否相等
/*
bool isSame(Cube &c1,Cube &c2)
{
if(c1.get_H() == c2.get_H() && c1.get_W() == c2.get_W() && c1.get_L() == c2.get_L())
{
return true;
}
else
return false;
}
*/
int main(int argc, char const *argv[])
{
Cube c1,c2;
c1.set_W(10);
c1.set_H(10);
c1.set_L(10);
c2.set_W(20);
c2.set_L(20);
c2.set_H(20);
cout << "c1的长宽高为:" << c1.get_L() << "," << c1.get_W() << "," << c1.get_H() << endl;
cout << "c2的长宽高为:" << c2.get_L() << "," << c2.get_W() << "," << c2.get_H() << endl;
cout << "c1的面积和体积:" << c1.get_area() << "," << c1.get_volume() << endl;
/*
bool is_s = isSame(c1,c2);
if(is_s == true)
cout << "c1和c2相等" << endl;
else
cout << "c1和c2不相等" << endl;
*/
bool is_s = c1.isSame(c2);
if(is_s == true)
cout << "c1和c2相等" << endl;
else
cout << "c1和c2不相等" << endl;
return 0;
}
##构造函数和析构函数
初步认识
#include <iostream>
#include <string>
using namespace std;
//构造函数和析构函数
//构造函数:创建对象时自动调用
//析构函数:对象销毁时自动调用
class Person
{
//1.1构造函数
//没有返回值,也不用写void
//函数名与类名相同,可以发生重载
public:
Person()
{
cout << "构造函数自动调用" << endl;
}
~Person()
{
cout << "析构函数的调用" << endl;
}
};
int main()
{
Person p1;
}
运行结果:
构造函数的分类及调用
#include <iostream>
#include <string>
using namespace std;
/*
两种分类方式:
1,参数分:有参构造和无参构造
2,类型分:普通构造和拷贝构造
三种调用方法:
1,括号法
2,显示法
3,隐式构造法
*/
class Person
{
//构造函数
public:
Person()
{
cout << "Person的无参构造函数调用(默认构造)" << endl;
}
Person(int a)
{
cout << "Person的有参构造函数调用" << endl;
}
//拷贝构造函数
Person(const Person &p)
{
//将传入的对象的所有属性 拷贝到‘我’身上
cout << "Person的拷贝构造函数调用" << endl;
}
};
//调用
void test()
{
//1,括号法
Person p; //默认构造函数调用
Person p1(10);//有参构造函数
Person p2(p1);
//2,显示法
//3,隐式转换法
}
int main()
{
test();
}

#include <iostream>
#include <string>
using namespace std;
/*
两种分类方式:
1,参数分:有参构造和无参构造
2,类型分:普通构造和拷贝构造
三种调用方法:
1,括号法
2,显示法
3,隐式构造法
*/
class Person
{
//构造函数
public:
Person()
{
cout << "Person的无参构造函数调用(默认构造)" << endl;
}
Person(int a)
{
cout << "Person的有参构造函数调用" << endl;
}
//拷贝构造函数
Person(const Person &p)
{
//将传入的对象的所有属性 拷贝到‘我’身上
cout << "Person的拷贝构造函数调用" << endl;
}
};
//调用
void test()
{
//1,括号法
// Person p; //默认构造函数调用
// Person p1(10);//有参构造函数
// Person p2(p1);
//注意事项:调用默认构造函数的时候,不要加括号(编译器会认为是一个函数的声明)
//2,显示法
Person p;
Person p2 = Person(10);
Person p3 = Person(p2); //等号右侧的部分叫做匿名对象:当前行执行结束后,系统会自动回收掉对象
//3,隐式转换法
}
int main()
{
test();
}
执行结果如上图
#include <iostream>
#include <string>
using namespace std;
/*
两种分类方式:
1,参数分:有参构造和无参构造
2,类型分:普通构造和拷贝构造
三种调用方法:
1,括号法
2,显示法
3,隐式构造法
*/
class Person
{
//构造函数
public:
Person()
{
cout << "Person的无参构造函数调用(默认构造)" << endl;
}
Person(int a)
{
cout << "Person的有参构造函数调用" << endl;
}
//拷贝构造函数
Person(const Person &p)
{
//将传入的对象的所有属性 拷贝到‘我’身上
cout << "Person的拷贝构造函数调用" << endl;
}
};
//调用
void test()
{
//1,括号法
// Person p; //默认构造函数调用
// Person p1(10);//有参构造函数
// Person p2(p1);
//注意事项:调用默认构造函数的时候,不要加括号(编译器会认为是一个函数的声明)
//2,显示法
// Person p;
// Person p1 = Person(10);
// Person p2 = Person(p2); //等号右侧的部分叫做匿名对象:当前行执行结束后,系统会自动回收掉对象
//3,隐式转换法、
Person p;
Person p1 = 10;
Person p2 = p1;
}
int main()
{
test();
}
拷贝构造函数的调用时机
#include <iostream>
using namespace std;
//拷贝函数的调用时机
//1,使用一个已经创建完毕的对象来初始化一个新对象
//2,值传递的方式给函数参数传值
//3,值方式返回局部对象
class Person
{
public:
Person()
{
cout << "Person默认构造函数调用" << endl;
}
Person(int age)
{
m_age = age;
cout << "Person有参构造函数调用" << endl;
}
Person(const Person & p)
{
m_age = p.m_age;
cout << "Person拷贝构造函数调用" << endl;
}
~Person()
{
cout << "Person析构函数调用" << endl;
}
}
void method_by_exchange(Person p)
{
}
int main()
{
//Person p1(20);
//Person p2(p1);
//cout << "p2的年龄:" << p2.m_age << endl;
//2,值传递的方式给函数参数传值
Person p;
method_by_exchange(p);
}

深拷贝与浅拷贝
浅拷贝带来的问题:
#include <iostream>
using namespace std;
//前置知识:当一个类初始化的时候,啥构造函数都没写,编译器自动提供默认构造和拷贝构造
//要是写了有参构造,编译器自动默认提供拷贝构造
//要是写了拷贝构造,编译器啥都不提供
class Person
{
public:
int m_age;
int *m_height; //身高,用指针来做 重点关注这个值
Person()
{
cout << "Person的默认构造函数调用" << endl;
}
Person(int age,int height)
{
m_age = age;
m_height = new int(height);
cout << "Person的有参构造函数调用" << endl;
}
~Person()
{
if (m_height != NULL)
{
delete m_height; //如果利用编译器提供的拷贝构造函数,会做浅拷贝操作
//浅拷贝带来的问题:堆区的内存重复释放
//如何解决??? 用深拷贝来做,自己写一个拷贝构造函数
m_height = NULL; //double free!!!!
}
cout << "Person的析构函数调用" << endl;
}
};
void test1()
{
Person p1(3,140);
cout << "p1的年龄为" << p1.m_age << endl;
cout << "p1的身高为" << *p1.m_height << endl;
Person p2(p1);
cout << "p2的年龄为" << p2.m_age << endl;
cout << "p2的身高为" << *p2.m_height << endl;
}
int main(int argc, char const *argv[])
{
test1();
return 0;
}

解决问题:深拷贝
#include <iostream>
using namespace std;
//前置知识:当一个类初始化的时候,啥构造函数都没写,编译器自动提供默认构造和拷贝构造
//要是写了有参构造,编译器自动默认提供拷贝构造
//要是写了拷贝构造,编译器啥都不提供
class Person
{
public:
int m_age;
int *m_height; //身高,用指针来做 重点关注这个值
Person()
{
cout << "Person的默认构造函数调用" << endl;
}
Person(int age,int height)
{
m_age = age;
m_height = new int(height);
cout << "Person的有参构造函数调用" << endl;
}
//现在我们来写一个拷贝构造函数来解决浅拷贝问题
Person(const Person &p)
{
m_age = p.m_age;
//m_height = p.m_height <---- 这行代码是编译器自动提供的代码,会引起浅拷贝的问题
//深拷贝操作:重新在堆区开辟一块空间!
m_height = new int(*p.m_height);
cout << "Person的拷贝构造函数调用" << endl;
}
~Person()
{
if (m_height != NULL)
{
delete m_height; //如果利用编译器提供的拷贝构造函数,会做浅拷贝操作
//浅拷贝带来的问题:堆区的内存重复释放
//如何解决??? 用深拷贝来做,自己写一个拷贝构造函数
m_height = NULL; //double free!!!!
}
cout << "Person的析构函数调用" << endl;
}
};
void test1()
{
Person p1(3,140);
cout << "p1的年龄为" << p1.m_age << endl;
cout << "p1的身高为" << *p1.m_height << endl;
Person p2(p1);
cout << "p2的年龄为" << p2.m_age << endl;
cout << "p2的身高为" << *p2.m_height << endl;
}
int main(int argc, char const *argv[])
{
test1();
return 0;
}
初始化列表
#include <iostream>
using namespace std;
//作用:c++提供了初始化列表语法,用来初始化属性
class Person
{
public:
int m_a,m_b,m_c;
public:
/* 传统初始化操作
Person(int a,int b,int c)
{
m_a = a;
m_b = b;
m_c = c;
}
*/
//初始化列表语法!
Person(int a,int b,int c):m_a(a),m_b(b),m_c(c)
{
}
};
void test()
{
Person p1 = Person(10,20,30);
cout << "p1的值为:" << p1.m_a << ',' << p1.m_b << ',' << p1.m_c << endl;
}
int main(int argc, char const *argv[])
{
test();
return 0;
}
类和对象
类对象作为类成员
B类中有对象A作为成员,A就是对象成员
重点:观察二者的构造和析构的调用顺序
#include <iostream>
#include <string>
using namespace std;
class Phone
{
public:
string mpname;
Phone(string pname)
{
mpname = pname;
cout << "Phone构造函数调用" << endl;
}
~Phone()
{
cout << "Phone的析构函数调用" << endl;
}
};
class Person
{
public:
string mname;
Phone mphone;
//本质: Phone mphone = phone; 隐式转换法!!!
Person(string name,string phone):mname(name),mphone(phone)
{
cout << "Person构造函数调用" << endl;
}
~Person()
{
cout << "Person的析构函数调用" << endl;
}
};
void test()
{
Person p1("tom","huawei");
cout << "p1的值为:" << p1.mname << endl;
cout << p1.mphone.mpname << endl;
}
int main()
{
test();
return 0;
}

运算符重载
加号运算符重载
作用:实现两个自定义数据类型相加的运算
实例:实现两个对象的属性值相加
#include <iostream>
using namespace std;
class Person
{
public:
int m_A;
int m_B;
Person(int a,int b)
{
m_A = a;
m_B = b;
}
};
//全局函数实现重载
Person operator+(Person &A,Person &B)
{
Person temp(0,0);
temp.m_A = A.m_A + B.m_A;
temp.m_B = A.m_B + B.m_B;
return temp;
}
int main()
{
Person p1(1,2);
Person p2(1,2);
Person p3 = p1 + p2;
//本质:Person p3 = operator(p1,p2);
cout << "p3的m_A:" << p3.m_A << endl;
cout << "p3的m_B:" << p3.m_B << endl;
}

左移运算符重载
#include <iostream>
using namespace std;
//通过友元来访问私有属性
//左移重载运算符只能通过全局函数来实现
class Person
{
friend int main();
friend ostream &operator<<(ostream &cout,Person &p);
private:
int m_A;
int m_B;
};
//全局函数实现左移运算符重载
ostream &operator<<(ostream &cout,Person &p) //本质 operator(cout , p)
{
//cout是标准输出流的对象
cout << "m_A:" << p.m_A << ",m_B:" << p.m_B;
return cout;
}
int main()
{
Person p1;
p1.m_A = 10;
p1.m_B = 20;
cout << p1;
}

递增运算符重载
分为两种:前置和后置
#include <iostream>
using namespace std;
//递增运算符重载
class MyInterger
{
friend void test();
friend ostream &operator<<(ostream &cout,MyInterger &p);
private:
int m_Num;
public:
MyInterger()
{
m_Num = 0;
}
//重载++运算符:前置++ 和 后置++ ,返回引用是为了一直对一个变量进行++操作
MyInterger &operator++()
{
m_Num++;
return *this;
}
//后置运算符重载
//int代表占位参数,可以用于区分前置和后置递增
MyInterger operator++(int)
{
//先返回结果,后递增
MyInterger temp = *this;
m_Num++;
return temp;
}
};
//左移运算符重载
ostream &operator<<(ostream &cout,MyInterger &p)
{
cout << p.m_Num << endl;
return cout;
}
void test01()
{
MyInterger i;
cout << ++(++i) << endl; //前置运算符重载
}
void test02()
{
MyInterger i;
cout << i << endl; //后置递增
}
int main()
{
test02();
}
赋值运算符重载
c++编译器至少给一个类添加四个函数
1,默认构造
2,默认析构
3,默认拷贝构造
4,赋值运算符 operator=,对属性进行值拷贝