c++构造函数和操作符重载

本文主要是分数加法减法为例说明:无参构造、有参构造、拷贝构造函数(复制构造函数)、=赋值操作符重载(赋值构造函数)、-操作符重载,重载为成员函数、+操作符重载,重载为友元函数、++操作符重载,重载为成员函数以及两个数的最大公约数计算方法。

注意事项

1.C++规定,赋值操作符“=”只能重载为成员函数;
2.操作符重载不能改变原操作符的优先级;
3.操作符重载不能改变操作数的个数;
4.操作符重载不能改变操作符的原有语义。

本类是以分数类说明构造函数和操作符重载的,之中两个私有变量m_a、m_b分别是分数的分子和分母。

Header.h头文件
#pragma once
#include <iostream>
#include <stdio.h>
#include "base.h" //头文件链接 https://blog.csdn.net/qq_35118533/article/details/105411376
#include <string.h>
using namespace std;
class Rational {
public:
 Rational();//无参构造
 ~Rational();//析构函数
 Rational(int a, int b); //有参构造
 //Rational(int a, int b) :m_a(a), m_b(b){ }
 //拷贝构造函数(复制构造函数)
 Rational(const Rational &cp_val);
 // Rational(Rational cp_val); //**error1** 
 //=赋值操作符重载(赋值构造函数)
 Rational &operator = (const Rational &val);
 //Rational operator = (Rational val); //**error2**
 //-操作符重载,重载为成员函数
 Rational operator - (const Rational &val);
 //+操作符重载,重载为友元函数
 friend Rational operator + (const Rational &val1, const Rational &val2);
 //++操作符重载,重载为成员函数
 Rational &operator ++ ();
 //打印函数,有一个重载版本
 const void myprint();
 const void myprint(const Rational &val);
  //计算最大公约数
 inline int caclMaxCommonDivisor(const Rational &val);
private:
 int m_a; //分子
 int m_b; //分母
 }

error1、error2行的代码,GCC和VS均通不过。根据《剑指Offer》上的解释,上述程序中的拷贝构造函数error1、error2传入的参数是Rational 的一个实例,所以由于是传值参数,我们把形参复制到实参会调用拷贝构造函数。因此如果允许拷贝构造函数传值,就会在拷贝构造函数内调用复制构造函数,就会形成无休止的递归调用从而导致栈溢出。

Source.cpp文件

#include <iostream>
#include "Header.h"
//无参构造
Rational::Rational() {
 m_a = 0;
 m_b = 1;
}
//析构函数
Rational::~Rational() {
 std::cout << "destructor" << std::endl;
}
//有参构造
Rational::Rational(int a, int b) {
 cout << "constructor with argument "<< endl;
 //因为b为分母,所以b不能为0,此处只为演示,具体要求看业务背景
 if(0==b){
  std::cout << "b=0非法,系统已将其改为1";
  b = 1;
 }
 m_a = a;
 m_b = b;
}
//拷贝构造函数
Rational::Rational(const Rational &cp_val) {
 cout << "copy constructor " << endl;
 m_a = cp_val.m_a;
 m_b = cp_val.m_b;
}
//赋值操作符
Rational &Rational::operator = (const Rational &val) {
 cout << "= assignment operator " << endl;
 m_a = val.m_a;
 m_b = val.m_b;
 return *this;
}
//++操作符重载,重载为成员函数
Rational &Rational::operator ++ () {
 cout << "++ assignment operator " << endl;
 m_a += m_b;
 //++m_b;
 return *this;
}
//+操作符重载,重载为友元函数
Rational operator + (const Rational &val1, const Rational &val2) {
 cout << "+ assignment operator ";
 //只有lvalue才能被赋值, a*val.a是一个表达式结果为右值,编译报错,实际上这行代码逻辑也不对
 //a*val.b += val.a*b;  //error 当时犯的错误没有删掉给大家提个醒,不要再出现类似错误
 Rational tmp;
 tmp.m_a = val1.m_a*val2.m_b + val1.m_b * val2.m_a;
 tmp.m_b = val1.m_b*val2.m_b;
 int maxDiv = tmp.caclMaxCommonDivisor(tmp);
 tmp.m_a /= maxDiv;
 tmp.m_b /= maxDiv;
 return tmp;
}
//-操作符重载,重载为成员函数
Rational Rational::operator - (const Rational &val) {
 cout << "- assignment operator ";
 Rational tmp;
 tmp.m_a = this->m_a*val.m_b - val.m_a * this->m_b;
 tmp.m_b = this->m_b*val.m_b;
 int maxDiv = tmp.caclMaxCommonDivisor(tmp);
 //std::cout <<" " << maxDiv << " ";
 //tmp.myprint();
 tmp.m_a /= maxDiv;
 tmp.m_b /= maxDiv;
 return tmp;
}
//打印函数
const void Rational::myprint(const Rational &val) {
 std::cout << val.m_a << "/" << val.m_b;
 std::cout << std::endl;
 return;
}
//重载打印函数
const void Rational::myprint() {
 std::cout << m_a << "/" << m_b;
 std::cout << std::endl;
 return;
}
//计算最大公约数 将分数的分子和分母看作两个两个数,计算这两个数的最大公约数
//此方法叫“辗转相除法”,而中国《九章算术》的更相减损法也可计算
inline int Rational::caclMaxCommonDivisor(const Rational &val) {
 int tmp_r = 0, tmp_a = val.m_a, tmp_b = val.m_b;
 if (val.m_a < 0) {
  tmp_a = -tmp_a;
 }
 while (tmp_b != 0) {
  tmp_r = tmp_b;
  tmp_b = tmp_a % tmp_b;
  if (0 == tmp_b)break;
  tmp_a = tmp_r;
 }
 return tmp_r;
}

主函数 main.cpp
演示作用,调用类中函数进行说明和演示

#include <iostream>
#include "Header.h"
int main() {
    Rational test(99, 100);
    test.myprint();
    Rational test1 = test;
    test1.myprint();
    Rational test2(test);
    //test2(test); //error ()没有重载
    Rational a;
    PRINTF_DBG(" a=");
    a.myprint(a);
    Rational b(1, 2);
    PRINTF_DBG(" b=");
    b.myprint();
    Rational c(3, 4);
    PRINTF_DBG(" c=");
    c.myprint();
    Rational d(5, 6);
    PRINTF_DBG(" d=");
    d.myprint();	
    Rational e;
    PRINTF_DBG(" e=");
    e.myprint();
    e = a + b + c + d;
    a.myprint();
    PRINTF_DBG(" e=");
    e.myprint();
    e = a;
    PRINTF_DBG(" e=");
    e.myprint();
    e = a - b - c - d;
    e.myprint();
    for (size_t i = 0; i < 5; i++){
       ++e;
       e.myprint();
    }
    getchar();
    return 0;
}

运算结果:
在这里插入图片描述
2. 当某对象没被初始化,这时运用赋值运算符调用的是拷贝构造函数;否则调用的是赋值运算符重载函数;
参考文献:
https://www.cnblogs.com/alantu2018/p/8459250.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值