4.5.4 赋值运算符重载
示例:
#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;
};
void test01()
{
Person p1(18);
Person p2(20);
Person p3(30);
p3 = p2 = p1;
cout << "p1的年龄为:" << *p1.m_Age << endl;
cout << "p2的年龄为:" << *p2.m_Age << endl;
cout << "p3的年龄为:" << *p3.m_Age << endl;
}
int main(void)
{
test01();
system("pause");
return 0;
}
4.5.5 关系运算符重载
示例:
#include <iostream>
#include <string>
using namespace std;
//关系运算符重载
class Person
{
public:
Person(string name, int age)
{
m_Name = name;
m_Age = age;
}
//重载==关系运算符
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;
}
string m_Name;
int m_Age;
};
void test01()
{
Person p1("张三", 18);
Person p2("张三", 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;
}
int main(void)
{
test01();
system("pause");
return 0;
}
4.5.6 ()运算符重载
示例:
#include <iostream>
#include <string>
using namespace std;
//函数调用运算符重载 ()
//打印输出类
class MyPrint
{
public:
//重载函数调用运算符
void operator()(string test)
{
cout << test << endl;
}
};
//加法类
class MyAdd
{
public:
int operator()(int num1, int num2)
{
m_Num1 = num1;
m_Num2 = num2;
return m_Num1 + m_Num2;
}
int m_Num1;
int m_Num2;
};
void test()
{
MyPrint myPrint;
MyAdd myAdd;
int ret = myAdd(100, 200);
//由于使用起来非常类似于函数调用,因此称为仿函数
myPrint("hello world");
cout << ret << endl;
//匿名函数对象
cout << MyAdd()(100, 100) << endl;
}
int main(void)
{
test();
system("pause");
return 0;
}
4.6 继承
继承是面向对象三大特性之一
利用继承的技术,减少重复代码
4.6.1 继承的基本语法
语法:class 子类 : 继承方式 父类
子类也称为派生类,父类也称为基类
class A : public B;
派生类中的成员,包含两在部分:
》一类是从基类中继承过来的,一类是自己增加的成员
》从基类继承过来的表现其共性,而新增的成员体现其个性
4.6.2 继承方式
》公共继承
》保护继承
》私有继承
示例:
#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 = 10; //父类中保护权限成员到子类中依然是保护权限
//m_C = 10; 父类中私有权限成员子类不能访问
}
};
//保护继承
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 = 100; //父类中保护权限的成员,子类中变成保护权限成员
//m_C = 100; 父类中的私有成员,子类访问不到
}
};
//私有继承
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 = 100; //父类中保护成员,子类中变成私有成员
// m_C = 100; 父类中私有成员,子类访问不到
}
};
class GrandSon3 : public Son3
{
public:
void func()
{
/* Son3类中所有成员都变成了私有,它的子类不能访问
m_A = 1000;
m_B = 1000;
m_C = 1000;
*/
}
};
void test()
{
Son1 s1;
s1.m_A = 100;
//s1.m_B = 100; 保护仅限不能访问
}
void test01()
{
Son2 s1;
/* 保护权限类外不能访问
s1.m_A = 10;
s1.m_B = 10;
*/
Son3 s2;
/* 私有权限类外不能访问
s2.m_A = 10;
s2.m_B = 10;
*/
}
int main(void)
{
system("pause");
return 0;
}
4.6.3 继承中的对象模型
问题:从父类继承过来的成员,哪些属于子类对象中?
父类中所有非静态成员属性都会被子类继承下去
父类中私有成员属性被编译器隐藏了,因此访问不到,但在子类中确实继承了。
4.6.4 继承中构造和析构的顺序
子类继承父类后,当创建子类对象,也会调用父类的构造函数
问题:父类和子类的构造和析构顺序是谁先谁后?
继承中的构造和析构顺序如下:
先构造父类,再构造子类;
析构的顺序与构造的顺序相反