一、大于运算符重载
#include <iostream>
using namespace std;
class Student
{
public:
Student(string n, int i, float s)
{
this->id = i;
this->name = n;
this->scored = s;
}
bool operator>(Student &s)
{
if (this->scored > s.scored)
{
return true;
}
else
{
return false;
}
}
private:
string name;
int id;
float scored;
};
int main()
{
Student s1("bb", 10, 99);
Student s2("cb", 0, 59);
if (s1 > s2)
{
cout << "bb六" << endl;
}
else
{
cout << "cb六" << endl;
}
return 0;
}
二、关系运算符重载
#include <iostream>
using namespace std;
class Person
{
public:
Person(string name, int age)
{
this->m_name = name;
this->m_age = age;
}
int m_age;
string m_name;
bool operator==(Person &p)
{
if (this->m_name == p.m_name && this->m_age == p.m_age)
{
return true;
}
else
{
return false;
}
}
bool operator!=(Person &p)
{
if (this->m_name == p.m_name && this->m_age == p.m_age)
{
return false;
}
else
{
return true;
}
}
};
int main()
{
Person p1("qq", 18);
Person p2("qq", 18);
if (p1 == p2)
{
cout << "p1=p2" << endl;
}
else
{
cout << "p1!=p2" << endl;
}
if (p1 != p2)
{
cout << "p1!=p2" << endl;
}
else
{
cout << "p1=p2" << endl;
}
return 0;
}
三、赋值运算符重载
C++会至少给一个类添加4个函数:
1默认构造函数、
2.默认析构函数、
3.默认拷贝构造函数(对属性进行一个值拷,浅拷贝)
4.赋值运算符重载函数operator(对属性进行值拷贝、浅拷贝),
#include <iostream>
using namespace std;
class Person{
public:
Person(int age)
{
m_Age = new int(age);
}
~Person()
{
if(m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
}
//由于系统提供=重载函数是有问题的,所以我们自己再重载一次。
Person& operator=(Person &p)
{
//m_Age = p.m_Age; //编译器默认做的就是这句话。(浅拷贝)
if(m_Age != NULL) //自己提供深拷贝。
{
delete m_Age;
m_Age = NULL;
}
m_Age = new int(*p.m_Age);
return *this;
}
int *m_Age;
};
int main()
{
/*
Person p1("张三",18);
cout << "p1的姓名:" << p1.m_Name << " 年龄:" << p1.m_Age << endl;
Person p2 = p1;
cout << "p2的姓名:" << p2.m_Name << " 年龄:" << p2.m_Age << endl;
*/
Person p3(18);
Person p4(20); //有参构造函数 //Person p4 = p3; //拷贝构造函数(默认就是浅拷贝),我不调用重载函数
Person p5(30);
p5 = p4 = p3; //如果有连等的操作,以引用的方式来将对象返回。
cout << "p3的年龄:" << *p3.m_Age << endl;
cout << "p4的年龄:" << *p4.m_Age << endl;
cout << "p5的年龄:" << *p5.m_Age << endl;
return 0;
}
结论:
1.只要有属性开辟到堆区,那么使用对象给另一个对象赋值时,必须自己重新写operate这个重载函数来投共深拷贝
四、函数调用运算符重载
1.函数运算符()也是可以重载的
2、由于重载以后使用方法非常像函数的调用,因此称为仿函数
3.仿函数没有固定的写法,非常的灵活
#include <iostream>
using namespace std;
//函数调用运算符重载。
//设计打印类。
class Myprint{
public:
//重载函数调用运算符
void operator()(string text)
{
cout << text << endl;
}
};
//设计加法类
class Myadd{
public:
int operator()(int num1,int num2)
{
return num1 + num2;
}
};
void myint02(string text)
{
cout << text << endl;
}
int main()
{
//Myprint myint;
//m.operator()("helloworld");
//myint("helloworld"); //由于重载之后使用方式非常像函数的调用,因此称为仿函数。
//myint02("helloworld");
Myadd ma;
//int ret = ma.operator()(10,20);
//int ret = ma(10,20);
//cout << "ret = " << ret << endl; //30
cout << ma(10,20) << endl; //30
cout << Myadd()(10,20) << endl; //30
//Myadd() -> 无名函数对象 Myadd()(10,20);
//ma -> 有名函数对象 ma(10,20);
return 0;
}
五、继承
继承是面向对象三大特性之一。
有一些类与类之间存在一些特殊的关系,
例如: 有一个动物类,猫与狗都是属于动物,都有动物的共性,也有自己的个性。
我们发现,定义这些类的时候,下级的成员除了拥有上一级的共性,还有自己的特性。
这个时候我们就可以考虑利用继承的技术,减少重复的代码。
六、继承
案例:例如我们考到很多网页,都是由公共的头部、公共的底部,只有中心的内容不一样
子类也称为派生类,父类也称为基类
//继承语法:
//class 子类:继承方式 父类
//继承的好处:
//减少重复的代码
#include <iostream>
using namespace std;
//继承写法 -- 共性
class BasePage
{
public:
void head()
{
cout << "网址、书签、搜索栏、菜单栏、" << endl;
}
void right()
{
cout << "专题推荐" << endl;
}
void footer()
{
cout << "评论区、发帖子" << endl;
}
};
//继承语法:
//class 子类:继承方式 父类
class Page_one : public BasePage
{
public:
void content()
{
cout << "向袁隆平学习" << endl;
}
};
class Page_two : public BasePage
{
public:
void content()
{
cout << "从不哪一个红薯" << endl;
}
};
class Page_three : public BasePage
{
public:
void content()
{
cout << "马拉松遇难" << endl;
}
};
int main()
{
cout << "第一个网页内容图下" << endl;
Page_one po;
po.head();
po.right();
po.content();
po.footer();
cout << "第二个网页内容图下" << endl;
Page_two pt;
pt.head();
pt.right();
pt.content();
pt.footer();
cout << "第三个网页内容图下" << endl;
Page_three ps;
ps.head();
ps.right();
ps.content();
ps.footer();
return 0;
}
七、继承方式
继承语法:
class 子类:继承方式 父类
继承方式:
①公共继承
②保护继承
③私有继承
、
#include <iostream>
using namespace std;
//继承方式
//公共继承
class Base1{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son1:public Base1{ //公共继承
public:
void func()
{
m_A = 10; //公共属性 -> 公共属性(类内可以访问公共属性)
m_B = 20; //保护属性 -> 保护属性(类内可以访问保护属性)
//m_C = 30; //私有属性 -> 不可以访问
}
};
//保护继承
class Base2{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son2:protected Base2{ //保护继承
public:
void func()
{
m_A = 100; //公共属性 -> 保护属性(类内可以访问保护属性)
m_B = 200; //保护属性 -> 保护属性(类内可以访问保护属性)
//m_C = 300; //私有属性 -> 不可以访问
}
};
class GrandSon2:public Son2{
public:
void func()
{
m_A = 50; //保护属性 -> 保护属性(类内可以访问保护属性)
m_B = 50; //保护属性 -> 保护属性(类内可以访问保护属性)
}
};
//私有继承
class Base3{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son3:private Base3{
public:
void func()
{
m_A = 100; //公共属性 -> 私有属性(类内可以访问)
m_B = 200; //保护属性 -> 私有属性(类内可以访问)
//m_C = 300; //私有属性 -> 不可以访问。
}
};
class GrandSon3:public Son3{
public:
void func()
{
//m_A = 100; //私有属性 -> 不可以访问
//m_B = 100; //私有属性 -> 不可以访问
}
};
int main()
{
Son1 s1;
s1.m_A = 100; //公共属性 -> 公共属性(类外可以访问公共属性)
//s1.m_B = 200; //保护属性 -> 保护属性(类外不可以访问保护属性)
//s1.m_C = 300; //私有属性 -> 不可以访问
Son2 s2;
//s2.m_A = 100; //公共属性 -> 保护属性(类外不可以访问保护属性)
//s2.m_B = 200; //保护属性 -> 保护属性(类外不可以访问保护属性)
//s2.m_C = 300; //私有属性 -> 不可以访问
Son3 s3;
//s3.m_A = 100; //公共属性 -> 私有属性(类外不可以访问)
//s3.m_B = 200; //保护属性 -> 私有属性(类外不可以访问)
//s3.m_C = 300; //私有属性 -> 不可以访问。
return 0;
}
八、继承中的对称模型
问题:从父类中继承过来的成员,那些是属于子类对象上的?
#include <iostream>
using namespace std;
class Base
{
public:
int m_a;
protected:
int m_b;
private:
int m_c;
};
class son : public Base
{
public:
int m_d;
};
int main()
{
//1.计算父类对象的大小
cout << "sizeof(Base)" << sizeof(Base) << endl;
//父类中所有的非静态成员属性都会被子类继承下来。
//父类的私有成员属性是被编译器隐藏了,因此访问不到,但它确实是继承下来了
cout << "sizeof(son)" << sizeof(son) << endl;
return 0;
}
结论;
//父类中所有的非静态成员属性都会被子类继承下来。
//父类的私有成员属性是被编译器隐藏了,因此访问不到,但它确实是继承下来了
九、继承构造函数与析构的顺序?
子类继承父类以后。当创建子类对象时,
父亲先构造,子类再构造,析构则是相反
继承中构造与析构的顺序
#include <iostream>
using namespace std;
class Base
{
public:
Base()
{
cout << "Base构造" << endl;
}
~Base()
{
cout << "Base析构" << endl;
}
};
class Son : public Base
{
public:
Son()
{
cout << "son构造" << endl;
}
~Son()
{
cout << "son析构" << endl;
}
};
int main()
{
Base b;
Son s;
return 0;
}
十、继承中同名成员的处理方式
问题:当子类中与父类出现同名的成员,如何通过子类对象访问子类或者是父类中同名的数据
#include <iostream>
using namespace std;
//继承中同名成员处理方式
//1)访问子类同名成员,直接访问就可以了。
//2)访问父类同名成员,需要加作用域。
//设计父类
class Base{
public:
Base()
{
m_A = 10; //非静态成员属性
}
void func() //非静态成员函数
{
cout << "Base - func函数调用" << endl;
}
int m_A;
};
class Son:public Base{
public:
Son()
{
m_A = 20;
}
void func() //非静态成员函数
{
cout << "Son - func函数调用" << endl;
}
int m_A; //非静态成员属性
};
int main()
{
//1. 同名成员属性处理方式。
//Son s; //实例化子类的对象,就会先调用父类的构造函数,再调用子类的构造函数。
//cout << "Son下的m_A = " << s.m_A << endl; //子类对象访问子类成员,直接访问就可以了。
//cout << "Base下的m_A = " << s.Base::m_A << endl; //子类对象访问父类成员,需要加作用域。
//2. 同名成员函数处理。
Son s;
s.func(); //直接调用,则调用的是子类中同名成员。
s.Base::func(); //加作用域,则访问的是父类的函数。
return 0;
}
结论:
//访问子类同名成员,直接访问就可以了,
//访问父类同名成员,需要加作用域
十一、继承中同名的静态成员的处理方式。
问题:继承中同名的静态成员在子类中是如何访问的
静态成员与非静态成员出现同名情况。处理方式以一致
1)访问子类中静态成员,直接访问即可、
2)访问父类中静态成员函数,前面添加作用域
#include <iostream>
using namespace std;
class Base
{
public:
static int m_a;
static void func()
{
cout << "base - static void func()" << endl;
}
};
int Base::m_a = 100;
class Son : public Base
{
public:
static int m_a;
static void func()
{
cout << "son - static void func()" << endl;
}
};
int Son::m_a = 200;
int main()
{
//计算子类对象的大小
cout << sizeof(Son) << endl;
//通过对象访问
Son s;
cout << s.m_a << endl;
cout << s.Base::m_a << endl;
//通过类名访问
cout << Base::m_a << endl;
cout << Son::m_a << endl;
//通过对象访问
s.func();
s.Base::func();
//通过类名访问
Son::func();
Base::func();
Son::Base::func();
return 0;
}
十二、多继承的语法(不推荐使用,可能会很麻烦,和别人合作不方便)
C++中允许一个类继承多个类
语法: class 子类:继承方式 父类1,继承方式 父类二…………
多继承可能会引起父类中同名成员出现,需要加作用域加以区分
#include <iostream>
using namespace std;
class Base1
{
public:
Base1()
{
m_a = 100;
}
int m_a;
};
class Base2
{
public:
Base2()
{
m_a = 200;
}
int m_a;
};
//class 子类:继承方式 父类1,继承方式 父类二…………
class Son : public Base1, public Base2
{
public:
Son()
{
m_c = 300;
m_d = 400;
}
int m_c;
int m_d;
};
int main()
{
cout << sizeof(Son) << endl;
//当名字不同时访问如下
Son s;
cout << s.Base1::m_a << endl;
cout << s.Base2::m_a << endl;
cout << s.m_c << endl;
cout << s.m_d << endl;
return 0;
}