代码之家  ›  专栏  ›  技术社区  ›  bolov

如何编写C++吸气剂和定位器

  •  4
  • bolov  · 技术社区  · 8 年前

    如果我需要为一个属性编写setter和/或getter,我会这样编写它:

    struct X { /*...*/};
    
    class Foo
    {
    private:
        X x_;
    
    public:
        void set_x(X value)
        {
            x_ = value;
        }
        X get_x()
        {
            return x_;
        }
    };
    

    但是我听说这是 爪哇风格 写定位器和吸气剂,我应该写在C++风格。此外,我被告知这是不合理的,甚至是不正确的。那是什么意思?如何在C++中编写设置器和吸气剂?


    假设对getter和/或setter的需求是合理的 . 例如,也许我们在setter中做了一些检查,或者我们只写getter。

    5 回复  |  直到 7 年前
        1
  •  9
  •   Caleth    8 年前

    Foo

    class Foo
    {
         X x_;
    public:
              X & x()       { return x_; }
        const X & x() const { return x_; }
    }
    

    X

     Foo f;
     f.x() = X { ... };
    

    class Foo
    {
         X x_;
    public:
         X x() const { return x_; }
         void x(X x) { x_ = std::move(x); }
    }
    

    x

        2
  •  6
  •   Jerry Coffin    8 年前

    const

    template <class T>
    class checked {
        T value;
        std::function<T(T const &)> check;
    
    public:
        template <class checker>
        checked(checker check) 
            : check(check)
            , value(check(T())) 
        { }
    
        checked &operator=(T const &in) { value = check(in); return *this; }
    
        operator T() const { return value; }
    
        friend std::ostream &operator<<(std::ostream &os, checked const &c) {
            return os << c.value;
        }
    
        friend std::istream &operator>>(std::istream &is, checked &c) {
            try {
                T input;
                is >> input;
                c = input;
            }
            catch (...) {
                is.setstate(std::ios::failbit);
            }
            return is;
        }
    };
    

    checked<int> foo([](auto i) { return std::min(std::max(i, 0), 10); });
    

    foo

    std::cout << "Please enter a number from 0 to 10: ";
    std::cin >> foo; // inputs will be clamped to range
    
    std::cout << "You might have entered: " << foo << "\n";
    
    foo = foo - 20; // result will be clamped to range
    std::cout << "After subtracting 20: " << foo;
    

    operator T

    bar std::tuple<int, int>

        3
  •  4
  •   bolov    8 年前

    class Foo
    {
    private:
        X x_;
    
    public:
        auto x()       -> X&       { return x_; }
        auto x() const -> const X& { return x_; }
    };
    

    C++11 int

    class Foo1
    {
    private:
        X x_;
    
    public:
        void set_x(const X& value)
    //             ^~~~~  ^
        {
            x_ = value;
        }
    
        const X& get_x()
    //  ^~~~~  ^
        {
            return x_;
        }
    };
    

    get_x const . 这是C++原理的一部分。 const正确性 .

    上述解决方案不允许您从 康斯特 对象:

    const Foo1 f;
    
    X x = f.get_x(); // Compiler error, but it should be possible
    

    这是因为 盖特克斯 不能对常量对象调用非常量方法。这样做的原因是非常量方法可以修改对象,因此对常量对象调用它是非法的。

    因此,我们进行必要的调整:

    class Foo2
    {
    private:
        X x_;
    
    public:
        void set_x(const X& value)
        {
            x_ = value;
        }
    
        const X& get_x() const
    //                   ^~~~~
        {
            return x_;
        }
    };
    

    以上变量正确。但是在C++中,还有一种写C++的方法,即C++ + ISH和更少的Java ISH。

    有两件事要考虑:

    class Foo
    {
    private:
        X x_;
    
    public:
        X&       x()        { return x_; }
        const X& x() const  { return x_; }
    };
    

    int foo() auto foo() -> int

    
    

    Foo2 f;
    X x1;
    
    f.set_x(x1);
    X x2 = f.get_x();
    

    Foo f;
    X x1;
    
    f.x() = x1;
    X x2 = f.x();
    
    const Foo cf;
    X x1;
    
    //cf.x() = x1; // error as expected. We cannot modify a const object
    X x2 = cf.x();
    

    && x_

    class Foo
    {
    private:
        X x_;
    
    public:
        auto x() const& -> const X& { return x_; }
        auto x() &      -> X&       { return x_; }
        auto x() &&     -> X&&      { return std::move(x_); }
    
    };
    

        4
  •  0
  •   gabry    8 年前

    class Foo
    {
    private:
        X x_;
    public:
        void x(const X &value) { x_ = value; }
        const X &x() const { return x_; }
    };
    

    Foo f;
    X obj;
    f.x(obj);
    X objcopy = f.x(); // get a copy of f::x_
    const X &objref = f.x(); // get a reference to f::x_
    

    X &x() { return x_; }
    

    Foo f;
    X obj;
    f.x() = obj; // replace inner object
    f.x().int_member = 1; // replace a single value inside f::x_
    

        5
  •  0
  •   Hot Since 7cc    7 年前