2012-12-06 12 views
6

Na przykład:Czy można usunąć kwalifikator const, gdy wywołanie pochodzi z tej samej nieobciążonej wersji przeciążonej funkcji składowej?

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); 
    } 
}; 

Chodzi o to, chcę uniknąć powtarzania tej samej logiki wewnątrz stałej FINDB i bez stałej funkcji składowej FINDB.

+0

Wydaje lubisz odniesień dużo. –

+0

Nie ma sensu używanie wskaźników lub kopii, jeśli nie są potrzebne – dchhetri

Odpowiedz

7

Tak, można rzutować obiektu do const, zadzwoń wersję const, a następnie rzucić wynik na udziały const:

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

Casting dala const jest bezpieczny tylko wtedy, gdy dany obiekt nie został uznany const. Ponieważ jesteś członkiem funkcji innej niż const, możesz o tym wiedzieć, ale to zależy od implementacji. Rozważ:

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; 
}; 

Ogólnie rzecz biorąc, moje funkcje członka są krótkie, więc powtórzenia są dopuszczalne. Czasami możesz uwzględnić implementację w funkcji prywatnego szablonu i wywołać ją z obu wersji.

+2

"Ponieważ jesteś w metodzie niestałej, wiesz, że tak jest." co masz na myśli? Metoda non-const może bardzo dobrze zwrócić obiekt 'const'. –

+2

jeśli masz prywatną funkcję pomocnika, a nie jest ona funkcją typu const-member, to jak mogę ją wywołać z wersji const bez usuwania stałej? Jak mogę nazwać tę niestałą prywatną funkcję pomocnika ze stałej funkcji publicznej. Czy nadal nie narzekałby na stałość tego? – dchhetri

1

myślę, że korzystając rzucać tutaj jest ok, ale jeśli na pewno chcesz tego uniknąć, można użyć jakiegoś szablonu Magic:

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(); 
} 
+0

O, fajna sztuczka, ale to jest przesada, a moim zdaniem pogorszyłoby to sytuację. – dchhetri

+0

@ user814628, Zgadzam się, chciałem tylko, żeby działało. – Lol4t0

Powiązane problemy