C/C++教程

C++ 学习日记-算符重载、继承

本文主要是介绍C++ 学习日记-算符重载、继承,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、大于运算符重载

#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;
}

这篇关于C++ 学习日记-算符重载、继承的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!