Day14.成员函数和全局函数//链表货物类//友元函数//操作符重载相关

成员函数和全局函数

先看一段下面的代码:

class Test1
{
public:
	int a;
	int b;
public:
	Test1(int a, int b)
	{
		this->a = a;
		this->b = b;
	}
};

Test1 T_add(Test1 &t1, Test1 &t2)
{
	Test1 t3;
	t3.a = t1.a + t2.a;
	t3.b = t1.b + t2.b;
	return t3;
}
假设上面的代码是可以执行的,且没有其他的错误,这时候F7编译就会提示错误:

error C2512: “Test1”: 没有合适的默认构造函数可用
错误在Test1 t3这里,没有合适的构造函数,如何解决呢??

解决办法:

//全局函数
Test1 T_add(Test1 &t1, Test1 &t2)
{
    Test1 t3;
    t3.a = t1.a + t2.a;
    t3.b = t1.b + t2.b;
    return t3;
}


public:
	Test1(int a=0, int b=0)
	{
		this->a = a;
		this->b = b;
	}
	//成员函数
	Test1 T_add(Test1 &t1, Test1 &t2)
	{
		Test1 t3;
		t3.a = t1.a + t2.a;
		t3.b = t1.b + t2.b;
		return t3;
	}
给出完整的代码;

#include "iostream"
using namespace std;

class Test
{
public:
    int a;
    int b;
public:
    //构造函数
    Test(int a=0, int b=0)
    {
        this->a = a;
        this->b = b;
    }

public:
    //成员函数
    Test M_add( Test &t2)
    {
        this->a = this->a + t2.a;
        this->b = this->b + t2.b;
        return *this;
    }
    void print()
    {
        cout << a << endl;
        cout << b << endl;
    }
};
//全局函数
Test G_add(Test &t1, Test &t2)
{
    Test t3;
    t3.a = t1.a + t2.a;
    t3.b = t1.b + t2.b;
    return t3;
}

void main()
{
    Test t1(1, 2), t2(3, 4);
    Test t3;
    //全局函数
    t1 = G_add( t1 , t2);
    t1.print();
    //成员函数
    t1.M_add(t2);
    t1.print();

    system("pause");
}
成员函数如何变成全局函数?

全局函数如何变成成员函数?

根据Day13天的学习,我们知道在构造函数调用时,C++编译器是这样改变的:

	Test(int a=0, int b=0)
	{
		this->a = a;
		this->b = b;
	}
	Test(Test *pthis, int a, int b)
	{
		this->a = a;
		this->b = b;
	}

会自动加上this指针,这就是全局函数和成员函数的定义上的区别。

总计:

1. 从成员函数转化为全局函数,只需要加一个this指针(指向本类的类指针)

2. 从全局函数转化为类的成员函数时,需要减一个左操作数参数(第一个参数)


链表货物类

例子;某商店经销一种货物。货物购进和卖出时以箱为单位,各箱的重量不一样,因此,商店需要记录目前库存的总重量。现在用C++模拟商店货物购进和卖出的情况。

#include "iostream"
using namespace std;

class Goods
{
private:
	int weight;
	static int total_weight;
public:
	Goods(int w)
	{
		weight = w;
		total_weight += w;
	}
	int getweight()
	{
		return weight;
	}
	static int gettotalweight()
	{
		return total_weight;
	}
	Goods *next;
};
int Goods::total_weight = 0;
void buy(Goods * &f, Goods * &r, int w)
{
	Goods *p = new Goods(w);
	p->next = NULL;
	if (f == NULL) f = r = p;
	else
	{
		r->next = p;
		r = r->next;
	}
}
void sale(Goods * &f, Goods * &r)
{
	if (f == NULL)
	{
		cout << "there are no more goods" << endl;
		return;
	}
		
	Goods *q = f;
	f = f->next;
	delete q;
	cout << "saled." << endl;
}
void main()
{
	Goods *head = NULL, *end = NULL;
	int w, choice;
	do
	{
		cout << "Key 0 is over \nKey 1 is buy \nKey 2 is sale" << endl;
		cout << "please enter your choice:" << endl;
		cin >> choice;
		switch (choice)
		{
		case 1:
			cout << "enter weight:" << endl;
			cin >> w;
			buy(head, end, w);
			break;
		case 2:
			cout << "sale begin" << endl;
			sale(head, end);
			cout << "sale end:" << endl;
			break;
		case 0:
			break;
		}
		cout << "Now total weights are:" << Goods::gettotalweight() << endl;
	} while (choice);
	system("pause");
}

友元函数类

友元函数可以通过函数参数访问类的private成员变量

普通函数如何访问私有成员变量呢?

#include "iostream"
using namespace std;

class Test
{
private:
	int a;
	int b;
public:
	Test(int a, int b)
	{
		this->a = a;
		this->b = b;
	}
	int geta()
	{
		return a;
	}
	friend int func(Test *p, int a);
};
int func(Test *p, int a)
{
	p->a = a;
	return p->a;
}
void main()
{
	Test t1(1,2);
	//通过get函数获取private
	cout << t1.geta() << endl;
	//通过friend友元函数
	cout<<func(&t1, 10)<<endl;
	system("pause");
}
这是友元函数,下面看友元类:

class A
{
	friend class B;
private: 
	int x;
public:
	void print()
	{
		cout << x << endl;
	}
};

class B
{
private:
	A AObj;
public:
	void set(int i)
	{
		AObj.x = i;
	}
	void print()
	{
		AObj.print();
	}
};
void main()
{
	B Bobj;
	Bobj.set(10);
	Bobj.print();
	system("pause");
}

运算符重载

不能重载的运算符:  .   ::    .*     ?:       sizeof

首先打个桩,基础的代码写出来:

#include "iostream"
using namespace std;

class complex
{
public:
	int a;
	int b;
public:
	complex(int a = 0, int b = 0)
	{
		this->a = a;
		this->b = b;
	}
	void print()
	{
		cout << a << "+" << b << "i" << endl;
	}
};
complex comadd(complex &c1, complex &c2)
{
	complex tmp;
	tmp.a = c1.a + c2.a;
	tmp.b = c1.b + c2.b;
	return tmp;
}
void main()
{
	//int是基础类型,C++编译器已经实现了+
	int a = 10;
	int b = 20;
	a = a + b;
	
	complex c1(1, 2), c2(3, 4);
	//complex是一个自定义类型,C++不知道如何+
	//但是C++编译器会提供一个机制,让你实现自定义类型+
	complex c3 = comadd(c1, c2);
	c3.print();
	system("pause");
}

继续深化:

#include "iostream"
using namespace std;

class complex
{
public:
	int a;
	int b;
public:
	complex(int a = 0, int b = 0)
	{
		this->a = a;
		this->b = b;
	}
	void print()
	{
		cout << a << "+" << b << "i" << endl;
	}
};

//complex comadd(complex &c1, complex &c2)
complex operator+(complex &c1, complex &c2)
{
	complex tmp;
	tmp.a = c1.a + c2.a;
	tmp.b = c1.b + c2.b;
	return tmp;
}
void main()
{
	//int是基础类型,C++编译器已经实现了+
	int a = 10;
	int b = 20;
	a = a + b;
	
	complex c1(1, 2), c2(3, 4);
	//complex是一个自定义类型,C++不知道如何+
	//但是C++编译器会提供一个机制,让你实现自定义类型+
	//第一步:函数实现
	complex c3 = comadd(c1, c2);
	//第二步:operator实现
	complex c3 = operator+(c1, c2);
	//第三部:+实现
	complex c3 = c1+c2;
	c3.print();
	system("pause");
}
总结

1.运算符函数是一种特殊的成员函数或友元函数

2.成员函数的语法形式为:

        类型 类名::operator op(参数表)

        {*******************************}

3.一个运算符被重载后,原有意义没有失去,只是定义了相对一特定类的一个新运算符


用成员函数或友元函数重载运算符

1. 成员函数实现,如上面的代码实现的;

2.如果成员函数为private私有成员,用友元函数实现,只需要在类的定义中加上:

class complex
{
public:
	int a;
	int b;
************
}

	int a;
	int b;
	friend complex operator+(complex &c1, complex &c2);
3.全局函数实现比较简单, 如何使用成员函数实现呢????

        目标:通过类的成员函数,完成操作符重载

        1 要承认操作符重载是一个函数,要写函数原型

        2 写出函数调用语言

c1.operator - c2;

        3 完善函数原型

complex operator-(complex &c2)


完整的代码实现:

#include "iostream"
using namespace std;

class complex
{
private:
	int a;
	int b;
	friend complex operator+(complex &c1, complex &c2);
public:
	complex(int a = 0, int b = 0)
	{
		this->a = a;
		this->b = b;
	}
	void print()
	{
		cout << a << "+" << b << "i" << endl;
	}
	complex operator-(complex &c2)
	{
		complex tmp;
		tmp.a = tmp.a - c2.a;
		tmp.b = tmp.b - c2.b;
		return tmp;
	}
};

//complex comadd(complex &c1, complex &c2)
complex operator+(complex &c1, complex &c2)
{
	complex tmp;
	tmp.a = c1.a + c2.a;
	tmp.b = c1.b + c2.b;
	return tmp;
}
void main()
{
	//int是基础类型,C++编译器已经实现了+
	int a = 10;
	int b = 20;
	a = a + b;
	
	complex c1(1, 2), c2(3, 4);
	//complex是一个自定义类型,C++不知道如何+
	//但是C++编译器会提供一个机制,让你实现自定义类型+
	//第一步:函数实现
	//complex c3 = comadd(c1, c2);
	//第二步:operator实现
	//complex c3 = operator+(c1, c2);
	//第三部:+实现
	complex c3 = c1+c2;
	c3.print();

	//第二步:operator
	//complex c4 = c1.operator-(c2);
	//第三步:-实现
	complex c4 = c1 - c2;
	c4.print();
	system("pause");
}

还有前置++,后置++, 前置--,后置--,具体内容看视频,我过了。。

http://pan.baidu.com/s/1kTnFb8N

http://pan.baidu.com/s/1mglBgqk


总结:



留个例子吧,建立一个描述三维坐标的类Tri_coor,重载运算符“+” “++” “=”,实现简单的算术运算。

答案:


C++中不能用友元函数重载的运算符有:   =    ()    [ ]      ->


项目开发中运算符重载的重点和难点

以 [ ] 为例,看下面的两句代码:

    for(int i=0; i<a1.length(); i++)
    {
        a1.setData(i, i);  
        //a[i] = 1;
    }
    
    for(int i=0; i<a1.length(); i++)
    {
        printf("array %d: %d\n", i, a1.getData(i));
	// printf("array %d: %d\n", i, a1[i]));
    }
要使用[ ]实现操作符的重载,见注释中。

a1[i]
要这样改写

int operator= (int i)

但是如果直接这样实现这句:

a[i] = 1;
就会出现问题,左操作数必须为左值,这时候记住一句话:

函数返回值当左值,需要返回一个引用

int& operator= (int i)
完整的功能代码,给出下载地址:

http://pan.baidu.com/s/1ntzMlQT



总结一下代码:

//通过类的成员函数实现-操作
complex operator-(complex &c2)
{
	complex tmp;
	tmp.a = this->a - c2.a;
	tmp.b = b - c2.b;
	return tmp;
}

complex operator+(complex &c2)
{
	complex tmp;
	tmp.a = this->a + c2.a;
	tmp.b = b + c2.b;
	return tmp;
}

//前置--
complex& operator--()
{
	this->a--;
	this->b--;
	return *this;
}

//前置++
complex& operator--()
{
	this->a++;
	this->b++;
	return *this;
}

//后置--
complex operator--(int)
{
	complex tmp = *this;
	this->a--;
	this->b--;
	return tmp;
}

//后置++
complex operator--(int)
{
	complex tmp = *this;
	this->a++;
	this->b++;
	return tmp;
}


















































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值