如何创建可以访问私有成员和 operore += 符号的辅助函数?

How do I create a helper function that can access a private member and operatore += sign?

我的问题在最下面

我正在为标记创建一个模块以封装在 0 到 100 之间。

到目前为止,我有几个运算符和转换重载函数:

class Mark {   
      int mark;

   public:

      Mark(); //constructor
      ~Mark(); //deconstructor
      Mark(int value); // mark is created using int value that sets the value of mark

      
      void setEmpty(); // mark = 0
      bool isValid()const; //checks if mark is valid

      //type conversion
      operator int() const; // mark casted to an int. result would be value of the mark or zero if mark is invalid
      operator double() const; //mark casted to a double for gpa..equivalent of int value
      operator char() const; // mark casted to char type...result would be grade latter value of mark

      //binary member operator
      Mark& operator += (int w); // int is added to the value of mark
      Mark& operator = (int i);  // mark is set to an integer
   };

这是主程序:

这是输出:

这是我的问题

我正在尝试为一个整数添加标记,return 该整数和任何无效标记都不会为该整数添加任何值。在主程序中,这是代码,它是最后两行。

Mark n(80), k(120);
cout << (val += n) << endl;
cout << (val += k) << endl;

输出为

140
140

如果他们说我上面的 += 运算符不明确,我就无法创建它。所以我在想这需要一个辅助函数吗?

关于如何执行此操作的任何帮助?

你的隐式转换削弱了你的类型。它是如此的弱,以至于现在变得模棱两可。由于您允许 Mark 自动转换为 int,因此您也可以只使用 int 并创建 stand-alone 函数来操作 int 而不是 [=15] =]s.

如果您坚持要操纵 Mark,您应该创建一个具有较小接口的类型来强制执行您的不变量。我不知道那些是什么,但假设 Mark 必须是 [0, 100] 中的 int。以下类型 (class) 将确保您无法使用该范围之外的值创建 Mark。任何附加功能都作为 stand-alone 函数添加,该函数采用 Mark 并操纵其 value 并确信这样的值永远不会在 [0,100] 之外,因为这是不可能的它超出了范围。

#include <iostream>
#include <stdexcept>

class Mark {
 public:
  Mark(int value = 0) {
    validate(value);
    m_value = value;
  }

  int value() const { return m_value; }

  void clear() { m_value = 0; }

  // I don't know why you need in-place modifications, but here they are and
  // they are exception safe.

  Mark& operator+=(const Mark& other) {
    int new_value = value() + other.value();
    validate(new_value);
    m_value = new_value;
    return *this;
  }

  Mark& operator-=(const Mark& other) {
    int new_value = value() - other.value();
    validate(new_value);
    m_value = new_value;
    return *this;
  }

 private:
  void validate(int value) const {
    // place your own logic here -- the purpose is to ensure that a Mark cannot
    // exist unless it is in a valid state.
    if (value < 0 || value > 100) {
      throw std::runtime_error("value must be in [0, 100]");
    }
  }

  int m_value = 0;
};

double to_double(const Mark& mark) {
  // replace with your own logic
  return mark.value() / 100.0;
}

char to_char(const Mark& mark) {
  // replace with your own logic
  if (mark.value() > 0 && mark.value() < 50) {
    return 'D';
  } else if (mark.value() >= 50 && mark.value() <= 100) {
    return 'A';
  } else {
    return 'X';
  }
}

std::ostream& operator<<(std::ostream& os, const Mark& m) {
  // replace with your own logic
  return os << "Mark(" << m.value() << ") / " << to_double(m) << " / "
            << to_char(m);
}

int main() {
  Mark m;
  Mark n(25);
  Mark k(100);
  // Mark p(-10); // uncommented will throw exception
  std::cout << m << "\n"
            << n << "\n"
            << k << "\n"
      // << p << "\n" // uncommented will throw exception
      ;
}

示例输出:

$ clang++ example.cpp -std=c++2a
$ ./a.out                             
Mark(0) / 0 / X
Mark(25) / 0.25 / D
Mark(100) / 1 / A