首页 > 编程语言 >C++核心知识回顾(自定义数据类型)

C++核心知识回顾(自定义数据类型)

时间:2023-01-10 02:00:11浏览次数:35  
标签:setValue const 自定义 数据类型 unsigned C++ Currency amount long

复习C++

自定义数据类型最灵活的方式就是使用C++的类结构

现在定义一个货币类型Currency:

enum signType{PLUS,MINUS};

class Currency {
public:
    Currency(signType theSign = PLUS,
             unsigned long theDollars = 0,
             unsigned int theCents = 0);
    ~Currency() {}
    void setValue(signType,unsigned long,unsigned int);
    void setValue(double);
    signType getSign() const { return sign; }
    unsigned long getDollars() const { return dollars; }
    unsigned int getCents() const { return cents; }
    Currency add(const Currency&) const;
    Currency& increment(const Currency&);
    void output() const;
private:
    signType sign;
    unsigned long dollars;
    unsigned int cents;
};

类的成员声明有两部分: public 和 private,分别代表公有和私有,公有部分所声明的是来操作类对象(或实例)的成员函数(方法),它们对类的用户是可见的,是用户与类对象进行交互的唯一手段。私有部分声明的是用户不可见的数据成员和成员函数,公有部分的地一个成员函数与类名相同

名称与类名相同的成员函数为构造函数,指明了第一个创建类对象的方法,无返回值,以~为前缀的函数是析构函数

set前缀的函数供给用户为类对象赋值,get前缀的函数返回调用对象的相应数据成员,关键字const指明这些函数不会改变调用对象的值,这种函数称为常量函数

成员函数add将调用对象的货币值与参数对象的货币值相加,然后返回相加后的结果,因为该成员函数不会改变调用对象的值,所以是一个常量函数

成员函数increment将参数对象的货币值加到调用对象上,改变了调用对象的值,所以不是一个常量函数

实现构造函数, 调用setValue函数进行赋值:

Currency::Currency(signType theSign, unsigned long theDollars, unsigned int theCents) {
    setValue(theSign,theDollars,theCents);
}

对于setValue函数有两个重载,第一个成员函数setValue首先验证参数值的合法性,只有参数值合法,才能用来给调用对象的私有数据成员赋值,如果参数不合法,就抛出一个类型为illegalParameterValue的异常

第二个成员函数setValue不验证参数值的合法性,仅使用小数点后面头两个数字,对于形如d1.d2d3的数,用计算机表示可能就是不精确的,比如应计算机表示数值5.29,实际存储的值可能比5.29略小,如果像下面这样抽取美分的值可能要出错:

cents = (unsigned int)((theAmount - dollars) * 100);

因为(theAmount-dollars)*100要比29稍微小一点,当程序将其转化为一个整数时,赋给cents的值是28而不是29,解决这个问题的方法是给theAmount加上0.001,这时,只要d1.d2d3用计算机表示后与实际值相比不少于0.001或不多于0.009,结果是正确的

void Currency::setValue(signType theSign, unsigned long theDollars, unsigned int theCents) {
    if (theCents > 99) {
        throw illegalParametrValue("Cents should be < 100");
    }
    sign = theSign;
    dollars = theDollars;
    cents = theCents;
}

void Currency::setValue(double theAmount) {
    if (theAmount < 0) {
        sign = MINUS;
        theAmount = -theAmount;
    } else {
        sign = PLUS;
    }
    dollars = (unsigned long) theAmount;
    cents = (unsigned int) ((theAmount + 0.001 - dollars) * 100);
}

接下来的add的代码:

Currency Currency::add(const Currency &x) const {
    long a1,a2,a3;
    Currency result;
    a1 = dollars * 100 + cents;
    if (sign == MINUS) a1 = -a1;
    a2 = x.dollars * 100 + x.cents;
    if (x.sign == MINUS) a2 = -a2;
    a3 = a1 + a2;
    if (a3 < 0) {
        result.sign = MINUS;
        a3 = -a3;
    } else {
        result.sign = PLUS;
    }
    result.dollars = a3/100;
    result.cents = a3 - result.dollars * 100;

    return result;
}

首先要将相加的两个对象转化为整数,result是局部对象,作为返回值必须被复制到调用环境中,此处是值返回

下面是increment和output的代码:

Currency& Currency::increment(const Currency &x) {
    *this = add(x);
    return *this;
}

void Currency::output() const {
    if (sign == MINUS) cout << '-';
    cout << '$' << dollars << '.';
    if (cents < 10) cout << '0';
    cout << cents;
}

保留关键字this指向调用对象,*this即调用对象,这里调用add函数,将x与调用对象相加,然后将相加的结果赋值给this,这个对象不是局部对象,当函数结束时,空间不会自动释放,所以返回引用

另一种写法:

enum signType{PLUS,MINUS};

class Currency {
public:
    Currency(signType theSign = PLUS,
             unsigned long theDollars = 0,
             unsigned int theCents = 0);
    ~Currency() {}
    void setValue(signType,unsigned long,unsigned int);
    void setValue(double);
    signType getSign() const { return amount < 0? MINUS:PLUS; }
    unsigned long getDollars() const { return (amount < 0? -amount:amount) / 100; }
    unsigned int getCents() const { return (amount < 0? -amount:amount)-getDollars()*100; }
    Currency add(const Currency&) const;
    Currency& increment(const Currency&);
    void output() const;
    Currency operator+(const Currency&) const;
    Currency operator+=(const Currency& x) { amount += x.amount}
private:
    long amount;
};

Currency::Currency(signType theSign, unsigned long theDollars, unsigned int theCents) {
    setValue(theSign,theDollars,theCents);
}

void Currency::setValue(signType theSign, unsigned long theDollars, unsigned int theCents) {
    if (theCents > 99) {
        throw illegalParametrValue("Cents should be < 100");
    }
    amount = theDollars * 100 + theCents;
    if (theSign == MINUS) amount -= amount;
}

void Currency::setValue(double theAmount) {
    if (theAmount < 0) {
        amount = (long) ((theAmount - 0.001) * 100);
    } else {
        amount = (long) ((theAmount + 0.001) * 100);
    }
}

Currency Currency::add(const Currency &x) const {
    Currency y;
    y.amount = amount + x.amount;
    return y;
}

操作符重载

借助操作符重载,使用+和+=替代add和increment,成员函数output用一个输出流的名字作为参数

class Currency {
public:
    Currency(signType theSign = PLUS,
             unsigned long theDollars = 0,
             unsigned int theCents = 0);
    ~Currency() {}
    void setValue(signType,unsigned long,unsigned int);
    void setValue(double);
    signType getSign() const { return amount < 0? MINUS:PLUS; }
    unsigned long getDollars() const { return (amount < 0? -amount:amount) / 100; }
    unsigned int getCents() const { return (amount < 0? -amount:amount)-getDollars()*100; }
    Currency add(const Currency&) const;
    Currency& increment(const Currency&);
    void output(ostream &out) const;
    Currency operator+(const Currency&) const;
    Currency operator+=(const Currency& x) { amount += x.amount; return *this; }
private:
    long amount;
};

void Currency::output(ostream& out) const {
    long theAmount = amount;
    if (theAmount < 0) {
        out << '-';
        theAmount = -theAmount;
    }
    long dollars = theAmount / 100;
    out << '$' << dollars << '.';
    int cents = theAmount - dollars * 100;
    if (cents < 10) out << '0';
    out << cents;
}

ostream& operator<<(ostream& out,const Currency& x) {
    x.output(out);
    return out;
}

Currency Currency::operator+(const Currency &x) const {
    Currency result;
    result.amount = amount + x.amount;
    return result;
}

友元

可以赋予别的类和函数直接访问该类私有成员的权利,可将这些类和函数声明为该类的友元

friend ostream& operator<<(ostream&, const Currency&);

将ostream& operator<<声明为currency类的友元,就可以直接访问currency类的所有成员,这时就不用另外定义成员函数output

ostream& operator<<(ostream& out,const Currency& x) {
    long theAmount = x.amount;
    if (theAmount < 0) {
        out << '-';
        theAmount = -theAmount;
    }
    long dollars = theAmount / 100;
    out << '$' << dollars << '.';
    int cents = theAmount - dollars * 100;
    if (cents < 10) out << '0';
    out << cents;
    return out;
}

标签:setValue,const,自定义,数据类型,unsigned,C++,Currency,amount,long
From: https://www.cnblogs.com/N3ptune/p/17038985.html

相关文章

  • C++ move()函数及priority_queue队列使用记录
    最近刷leetcode题,使用了move()函数及优先队列(堆)priority_queue数据结构,记录一下!1.move函数move(obj)函数的功能是把obj当做右值处理,可以应用在对象的移动上。右值引用......
  • 非数据类型变量:列表和字符串
    目录:一.列表1.列表的定义(1)空列表(2)索引2.list的操作方法(1)下标操作索引->值:列表[索引]值->索引:列表.index(值)(2)增加数据列表.append(数据)列表.insert(索引,数据)列表.ex......
  • C++ATM取存款机模拟程序[2023-01-09]
    C++ATM取存款机模拟程序[2023-01-09]ATM取存款机模拟程序要求:设计一个程序,当输入给定的卡号和密码(初始卡号和密码为123456)时,系统能登录ATM取款机系统,用户可以按照以下......
  • ES6-其他数据类型的解构赋值
    一.字符串的解构赋值1.以数组形式解构赋值const[a,,,b,c]='hello';console.log(a,b,c);//hlo2.以对象形式解构赋值//为什么字符串可......
  • C++引用【cherno课程学习】
    定义intmain(){inta=5;int*b=&a;//这个是指针int&ref=a;//这个是引用std::cin.get();}ref变量实际上不存在,只存在于源代码中,如果对......
  • C++实现顺序栈相关操作代码
    #include<iostream>#include<cstdlib>usingnamespacestd;#defineMAXSIZE100#defineOK1#defineERROR0#defineOVERFLOW-2typedefintStatus;typedefintElemtype......
  • C++实现链队列相关操作代码
    #include<iostream>#include<cstdlib>usingnamespacestd;#defineMAXSIZE100#defineOK1#defineERROR0typedefintStatus;typedefintElemtype;typedefstructQno......
  • C++成员初始化表达式列表的使用
    在类的构造函数中,首选使用成员初始化表达式列表去给类的对象赋值,这个比构造函数体种赋值速度更快,开销小解答如下:赋值初始化,通过在函数体内进行赋值初始化;列表初始化,在......
  • 软件开发入门教程网之C++ 引用
    引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。​​C++引用vs指针​​引用很容易......
  • ​​软件开发入门教程网之​​C++ 信号处理
     信号是由操作系统传给进程的中断,会提早终止一个程序。在UNIX、LINUX、MacOSX或Windows系统上,可以通过按Ctrl+C产生中断。有些信号不能被程序捕获,但是下表所列......