6

例えば:

struct B{};

struct A {

 const B& findB() const { /* some non trivial code */ }

 // B& findB() { /* the same non trivial code */ }

 B& findB() { 
       const A& a = *this;
       const B& b = a.findB();
       return const_cast<B&>(b);
  }
};

問題は、定数 findB および非定数 findB メンバー関数内で同じロジックを繰り返さないようにしたいということです。

4

2 に答える 2

7

はい、オブジェクトをconstにキャストし、バージョンを呼び出してconstから、結果を non- にキャストできconstます。

return const_cast<B&>(static_cast<const A*>(this)->findB());

キャスト アウェイconstは、問題のオブジェクトが最初に宣言されていない場合にのみ安全constです。あなたは非constメンバー関数にいるので、これが事実であることがわかりますが、それは実装に依存します。検討:

class A {
public:

    A(int value) : value(value) {}

    // Safe: const int -> const int&
    const int& get() const {
        return value;
    }

    // Clearly unsafe: const int -> int&
    int& get() {
        return const_cast<int&>(static_cast<const A*>(this)->get());
    }

private:
    const int value;
};

一般的に言えば、私のメンバー関数は短いので、繰り返しは許容範囲です。実装をプライベート テンプレート メンバー関数に分割して、両方のバージョンから呼び出すことができる場合があります。

于 2012-12-06T19:26:12.400 に答える
1

ここでキャストを使用しても問題ないと思いますが、どうしても避けたい場合は、テンプレート マジックを使用できます。

struct B
{
    B(const B&)
    {
        std::cout << "oops I copied";
    }
    B(){}
};

struct A {
public:
    A(){}
    A(const A&){ std::cout << "a is copied:(\n";}
    const B& findB() const { return getter(*this); }    
    B& findB() { return getter(*this); }

private:
    template <typename T, typename V>
    struct same_const
    {
        typedef V& type;
    };

    template <typename T, typename V>
    struct same_const<const T, V>
    {
        typedef const V& type;
    };

    template <typename T>
    static typename same_const<T,B>::type getter(T& t) { return t.b;}

    B b;

};

int main()
{
    A a;
    const A a_const;
    const B& b1 = a.findB();
    B& b2 = a.findB();

    const B& b3 = a_const.findB();
    //B& b4 = a_const.findB();
}
于 2012-12-06T19:52:53.080 に答える