Namaran

Code daily. Without assist.

2026-09-21

percentage_setter.cpp

#include <iostream>
#include <stdexcept>

class Percentage {
public:
    explicit Percentage(int value) : value_(value) {
        if (value < 0 || value > 100) {
            throw std::invalid_argument("out of range");
        }
    }
    int value() const { return value_; }
    void setValue(int value) { value_ = value; }
private:
    int value_;
};

int main() {
    Percentage p(50);
    p.setValue(150);
    std::cout << p.value() << "\n";
}

Percentageはコンストラクタで0100の不変条件を検査していますが、このコードは150を保持してしまいます。何が問題で、どう直せばよいでしょうか?

Answer

不変条件を検査しているのはコンストラクタだけで、後から値を変えるsetValueは同じ検査を一切していません。「型で不変条件を守る」という設計は、その値を変更しうるすべての経路が検査を通ることで初めて成り立ちます。コンストラクタだけ検査しても、検査を通らないsetValueのような抜け道が1つでもあれば、不変条件はいつでも破られます。setValueにもコンストラクタと同じ検査を入れれば直ります:

void setValue(int value) {
    if (value < 0 || value > 100) {
        throw std::invalid_argument("out of range");
    }
    value_ = value;
}