数据结构与算法----自定义类中函数与数据成员

近期在梳理知识,做一个小结,希望自己能多多使用
在头文件中:

enum sign {plus, minus};
	class Accruency
	{
	public:
	Accruency(sign s = plus, unsigned long d = 0, unsigned int c = 0);//构造函数,没有返回值,连void也不行哦
	~Accruency(){};//析构函数,同理//写的方法不对,忘记写大括号了,
	bool Set(sign s, unsigned long d, unsigned int c);
	bool Set(float a);
	sign Sign()const{return sgn;};
	unsigned long Dollars() const {return dollars;};//const位置放的不对;return 后面应该有分号
	unsigned int Cents() const{return cents;};//有函数体{}就不用再cpp中实现啦
	Accruency Add(const Accruency& x)const;//后面没有函数体,在cpp中实现也是可以的
	Accruency& Increment(const Accruency& x);
	void Output() const;
	private:
	sign sgn;//软件工程领域不建议在public中定义数据成员
	unsigned long dollars;
	int cents;

在对应cpp中

#include"stdafx.h"
#include"Accurrency.h"
#include"iostream"
//using namespace sst;//本想着用自定义空间,但好像不是很成功呢
using namespace std;
//Accurency::Accruency()
Accruency::Accruency(sign s, unsigned long d, unsigned int c)//给private成员赋值
{
	if(c > 99)//验证参数的合法性//这个我很少考虑,异常处理
	{
		;
	}
	sgn = s; 
	dollars = d;
	cents = c;
}
Accruency Accruency::Add(const Accruency& x)const//参数x与默认值相加
{
	Accruency ans;
	long a1,a2,a3;
	a1 = dollars*100 + cents;//dollars和cents都是正数,定义中得来的
	if(sgn == minus)
	{
		a1 = -a1;
	}
	a2 = x.dollars*100 + x.cents;
	if(x.sgn == minus)
	{
		a2 = -a2;
	}
	a3 = a1 + a2;
	//再把整型转换为对象ans中对应的数据,因为返回的是数据,为啥不是值呢啊????
	if(a3 < 0)
	{
		ans.sgn = minus;
		a3 = -a3;//此处忘记了
	}
	else
	{
		ans.sgn = plus;
	}
	ans.dollars = a3/100;//dollars:表达式必须是可修改的值 所以等式左端不能用 dollars
	ans.cents = a3%100;
	//ans.cents = a3 - ans.dollars*100;//这个没有上面的简单

	return ans;
}

bool Accruency::Set(sign s, unsigned long d, unsigned int c)
{
	if(c > 99)//验证数据的合法性
	{
		return false;
	}//后面的可以不写在else里面
	sgn = s; 
	dollars = d;
	cents = c;
	return true;
}

bool Accruency::Set(float a)
{
	//给private成员赋值
	if(a < 0)
	{
		sgn = minus;
		a = -a;
	}
	else
	{
		sgn = plus;
	}
	dollars = a;//这个比较巧妙了呢,float类型转long类型,丢失小数部分了,剩余整数,dollars也是long类型
	//if((a - dollars) > 0)
	cents = (a + 0.05 - dollars)*100;//不太懂此处的
	return true;
}

//与头文件中定义的不兼容,是因为 函数 increment 我给加了 const,变成了 Accruency& Accruency::Increment(const Accruency& x) const
Accruency& Accruency::Increment(const Accruency& x)
{
	*this = Add(x);
	return *this;
}
void Accruency::Output()const//报与头文件不兼容,是因为 定义时 缺少了const
{
	if(sgn == minus)
		cout<<"-";
	cout<<"$"<<dollars<<".";
	if(cents < 10)
		cout<<0;
	cout<<cents;
}

验证函数部分:

// Acc.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "iostream"
#include"Accurrency.h"
using namespace std;
//using namespace sst;//必须的有对应的头文件,否则命名空间为未命名状态//自定义命名空间
using namespace std; 
int _tmain(int argc, _TCHAR* argv[])
{
	Accruency g,h(plus,3,50),i,j;
	g.Set(minus,2,25);
	i.Set(-6.45);
	j = h.Add(g);
	j.Output();
	cout<<endl;
	i.Increment(h);
	cout<<endl;
	j = i.Add(g).Add(h);
	j.Output();
	cout<<endl;
	j = i.Increment(g).Add(h);
	j.Output();
	cout<<endl;
	i.Output();
	cout<<endl;
	system("pause");
	return 0;
}


部分内容小结:
1.构造函数初始化对象的,没有返回值,即没有像 void/int Fdd(int a, int b);
构造函数就是与类同名的,此处中没有 void 或者 int 哈
此处 Accruency(sign s = plus, unsigned long d = 0, unsigned int c = 0)此处;
最后没有函数体{}
2.析构函数是释放内存,销毁对象,与类同名,但有,且函数体为空,不能不写!!!Accruency(){}; 如果不写 {} 在VS2010中 会报错:无法解析外部函数,该函数在_wmain中被使用
【注意】析构函数被定义为空函数{},当Accruency对象超出作用域时,会自动调用析构函数,
3.在函数实现时,要考虑是否 验证数据的合法性,比如 此处中 cents 变量就不能超过100
4.对于正整数时 可以用 unsigned long a 这样确保了数据 都是正的;
对于 float a; long d;
d = a;时 就会把小数去掉,编程整型 ,会报警,最好加强制类型转换
5.软件工程领域,最好不要在public中定义数据成员
6.*this 指向当前对象,代表对象本身
7.在cpp中函数定义时,会报警 :/与头文件中定义的不兼容,是因为 定义处的函数与申明时函数不一致,看缺/多const
-------------------by ZWJ 2018.10.11 22:16----------------------

8.两种定义类对象的方式:
(1)Accruency f,g(plus,3,45),h(minus,10);
(2) Accruency *m = new Accruency(plus,8,12);
第一种:定义三个对象,f初始化为缺省值plus,0,0 ;g初始化为¥3.45,;h由于只有两个参数,则第三个参数采用默认参数0,被初始化为-¥10.0
第二种:定义一个指针m 指向该对象,对象的指针存储在m中,对象被初始化为-¥8.12
【冒号初始化】构造函数的冒号初始化给对象,数据成员,或者
详情看收藏!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

class Accer
{
public:
    //普通构造函数
    Accer(int nAns, int nAnm):aa(nAns),bb(nAnm)
    {
        cout << "common constructor function" << endl;
    }
private:
    int aa;
    int bb;
};

此处构造函数处有一个:
其实冒号后的内容是初始化成员列表,一般有三种情况:
1、对含有对象成员的对象进行初始化,例如,
类line有两个私有对象成员startpoint、endpoint,line的构造函数写成:
line(int sx,int sy,int ex,int ey):startpoint(sx,sy),endpoint(ex,ey){……}
初始化时按照类定义中对象成员的顺序分别调用各自对象的构造函数,再执行自己的构造函数
2、对于不含对象成员的对象,初始化时也可以套用上面的格式,例如,
类rectangle有两个数据成员length、width,其构造函数写成:
rectangle():length(1),width(2){}
rectangle(int x,int y):length(x),width(y){}
3、对父类进行初始化,例如,
CDlgCalcDlg的父类是MFC类CDialog,其构造函数写为:
CDlgCalcDlg(CWnd* pParent ): CDialog(CDlgCalcDlg::IDD, pParent)
其中IDD是一个枚举元素,标志对话框模板的ID
使用初始化成员列表对对象进行初始化,有时是必须的,有时是出于提高效率的考虑

猜你喜欢

转载自blog.csdn.net/u012719076/article/details/83019667