C++进阶:使用普通函数重载算数运算符

一般来说,如果可以利用现有的成员函数(接触类内部的函数越少越好),则应优先使用普通函数而不是友元函数。但是,不要仅仅为了将运算符重载为普通函数而不是友元函数而添加额外的访问函数

单文件 main.cpp

  1 #include <numeric>  // for std::gdb
  2 #include <iostream>
  3
  4 class Fraction
  5 {
  6 private:
  7     int m_numerator {};
  8     int m_denominator { };
  9
 10 public:
 11     explicit Fraction(int numerator, int denominator = 1)
 12         : m_numerator{ numerator }, m_denominator{ denominator }
 13     { }
 14
 15 	
 16     int getNumerator() const
 17     {
 18         return m_numerator;
 19     }
 20
 21     int getDenominator() const
 22     {
 23         return m_denominator;
 24     }
 25
 26     void reduce();
 27     void print();
 28 };
 29
 30 Fraction operator*(const Fraction& f1, const Fraction& f2);
 31 Fraction operator*(const Fraction& f1, int value);
 32 Fraction operator*(int value, const Fraction& f1);
 33
 34 Fraction operator*(const Fraction& f1, const Fraction& f2)
 35 {
 36     return Fraction{ f1.getNumerator() * f2.getNumerator(), f1.getDenominator() * f2.getDenominator() };
 37 }
 38
 39
 40 Fraction operator*(const Fraction& f1, int value)
 41 {
 42     return Fraction{ f1.getNumerator() * value, f1.getDenominator() };
 43 }
 44
 45 Fraction operator*(int value, const Fraction& f1)
 46 {
 47     return Fraction{ f1.getNumerator() * value, f1.getDenominator() };
 48 }
 49
 50 void Fraction::reduce()
 51 {
 52     int m_gcd{ std::gcd(m_numerator, m_denominator) };
 53     if (m_gcd) // Make sure we don't try to divide by 0
 54     {
 55         m_numerator /= m_gcd;
 56         m_denominator /= m_gcd;
 57     }
 58 }
 59 void Fraction::print()
 60 {
 61     Fraction::reduce();
 62     std::cout << m_numerator<< "/" << m_denominator << '\n';
 63 }
 64
 65 int main()
 66 {
 67     Fraction f1{ 1, 4};
 68     f1.print();
 69
 70     Fraction f2{ 1, 2 };
 71     f2.print();
 72
 73     Fraction f3{ f1 * f2 };
 74     f3.print();
 75
 76     Fraction f4{ 2 * f1 };
 77     f4.print();
 78
 79     Fraction f5{ f1 * 3 };
 80     f5.print();
 81
 82     Fraction f6{ Fraction{1, 2} * Fraction{2, 3} * Fraction{3, 4} };
 83     f6.print();
 84
 85     return 0;
 86 }
 87
                       

改写多文件
将类和声明放到头文件里面,为防止单个文件重复使用声明,加上条件编译保护机制。
具体操作:将上面4~32行放到Fraction.h文件加上标识符为FRACTION_H的头文件保护机制
Fraction.h

#ifndef FRACTION_H
#define FRACTION_H
class Fraction
{
private:
    int m_numerator {};
    int m_denominator { };

public:
    explicit Fraction(int numerator, int denominator = 1)
        : m_numerator{ numerator }, m_denominator{ denominator }
    { }


    int getNumerator() const
    {
        return m_numerator;
    }

    int getDenominator() const
    {
        return m_denominator;
    }

    void reduce();
    void print();
};

Fraction operator*(const Fraction& f1, const Fraction& f2);
Fraction operator*(const Fraction& f1, int value);
Fraction operator*(int value, const Fraction& f1);
#endif
  

将头文件Fraction.h的具体实现放入到Fration.cpp中,最好包含Fraction.h,表示结构上关系的清晰(不引入自会编译器自会寻找),再包含进所用到的头文件。
具体操作:将34~64行放入Fration.cpp中,因为求两数最大公约数的std::gcd是文件中的,也用到了std::cout,所以和也#include 进去。
Fration.cpp

#include "Fraction.h"
#include <numeric>
#include <iostream>
Fraction operator*(const Fraction& f1, const Fraction& f2)
{
    return Fraction{ f1.getNumerator() * f2.getNumerator(), f1.getDenominator() * f2.getDenominator() };
}


Fraction operator*(const Fraction& f1, int value)
{
    return Fraction{ f1.getNumerator() * value, f1.getDenominator() };
}

Fraction operator*(int value, const Fraction& f1)
{
    return Fraction{ f1.getNumerator() * value, f1.getDenominator() };
}
void Fraction::reduce()
{
    int m_gcd{ std::gcd(m_numerator, m_denominator) };
    if (m_gcd) // Make sure we don't try to divide by 0
    {
        m_numerator /= m_gcd;
        m_denominator /= m_gcd;
    }
}
void Fraction::print()
{
    Fraction::reduce();
    std::cout << m_numerator<< "/" << m_denominator << '\n';
}                      

剩下的就是main.cpp 了,将Fraction.h包含进来,删掉没用到的头文件就可以了。
main.cpp

#include "Fraction.h"

int main()
{
    Fraction f1{ 1, 4};
    f1.print();

    Fraction f2{ 1, 2 };
    f2.print();

    Fraction f3{ f1 * f2 };
    f3.print();

    Fraction f4{ 2 * f1 };
    f4.print();

    Fraction f5{ f1 * 3 };
    f5.print();

    Fraction f6{ Fraction{1, 2} * Fraction{2, 3} * Fraction{3, 4} };
    f6.print();

    return 0;
}

确保这个三个文件都在同一目录下面,然后就开始编译了。

在这里插入图片描述
单独编译各个文件都没有编译方面的问题。
在这里插入图片描述
使用lld链接也没有问题,运行可执行文件a.out按照预期输入了化简后的分数。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值