2009-10-04 5 views
2

Tout comme le titre demande, est-C++ ont l'équivalent de setitem et de getitem Python pour les classes?C++ ont un equivilent au __setitem__ Python

Fondamentalement, il vous permet de faire quelque chose comme ce qui suit.

MyClass anObject; 

anObject[0] = 1; 
anObject[1] = "foo"; 
+0

Cela peut être utile si vous expliquez ce qu'est "setitem/getitem for classes". – sellibitze

Répondre

6

essentiellement, vous surcharger l'opérateur d'indexation (operator[]), et renvoie une référence (il peut être lu aussi bien qu'écrites à)

6

Vous pouvez surcharger l'opérateur [], mais ce n'est pas tout à fait la même chose qu'une paire de méthodes getitem/setitem séparée, en ce sens que vous n'avez pas besoin de spécifier une gestion différente pour obtenir et définir.

Mais vous pouvez vous rapprocher en retournant un objet temporaire qui remplace l'opérateur d'affectation.

+0

Je pense que je comprends ce que vous dites. Pour remplacer le comportement d'une instruction comme "anObject [0] = 1", je devrais remplacer les deux opérateurs, mais le type de retour de l'opérateur [] doit être une instance distincte d'une classe qui remplace l'opérateur =? – Scott

+1

Oui. Alors les vrais problèmes commencent avec l'obtention. L'objet temporaire retourné ne sera pas du même type que le type "logique" (par exemple 'int' ou' string' dans votre exemple), il doit donc avoir une fonction 'value()' pour obtenir la valeur réelle. Vous pouvez améliorer cela légèrement en surchargeant l'opérateur de conversion, mais cela a ses propres inconvénients, et ne couvre pas toutes les situations, vous avez donc absolument besoin de la fonction 'value()' au minimum. –

+0

Cette technique est abordée dans le document C++ plus efficace, article 30, où Meyers se réfère à eux en tant que "classes proxy". Voici un exemple d'une question précédente. http://stackoverflow.com/questions/994488/what-is-proxy-class-in-c/994925#994925 – AFoglia

3

Il existe une discussion intéressante sur ce qui est possible (et ce qui ne l'est pas) en C++ avec les opérateurs d'indice dans this article.

1

Pour développer après Earwicker:

#include <string> 
#include <iostream> 

template <typename Type> 
class Vector 
{ 
public: 
    template <typename Element> 
    class ReferenceWrapper 
    { 
    public: 
     explicit ReferenceWrapper(Element& elem) 
     : elem_(elem) 
     { 
     } 

     // Similar to Python's __getitem__. 
     operator const Type&() const 
     { 
      return elem_; 
     } 

     // Similar to Python's __setitem__. 
     ReferenceWrapper& operator=(const Type& rhs) 
     { 
      elem_ = rhs; 
      return *this; 
     } 

     // Helper when Type is defined in another namespace. 
     friend std::ostream& operator<<(std::ostream& os, const ReferenceWrapper& rhs) 
     { 
      return os << rhs.operator const Type&(); 
     } 

    private: 
     Element& elem_; 
    }; 

    explicit Vector(size_t sz) 
    : vec_(sz) 
    { 
    } 

    ReferenceWrapper<const Type> operator[](size_t ix) const 
    { 
     return ReferenceWrapper<const Type>(vec_[ix]); 
    } 

    ReferenceWrapper<Type> operator[](size_t ix) 
    { 
     return ReferenceWrapper<Type>(vec_[ix]); 
    } 

private: 
    std::vector<Type> vec_; 
}; 

int main() 
{ 
    Vector<std::string> v(10); 
    std::cout << v[5] << "\n"; 

    v[5] = "42"; 
    std::cout << v[5] << "\n"; 
} 
+0

Maintenant, essayez 'v [5] .size()' pour obtenir la taille de la chaîne que vous avez stockée. Ne fonctionne pas Vous pouvez utiliser un cast très moche, ou 'std :: string & got = v [5];' suivi de 'got.size()', ou ajouter une fonction 'value()' 'ReferenceWrapper'. –

1

Ce n'est pas portable, mais MSVC a __declspec(property), qui permet également indexeurs:

struct Foo 
{ 
    void SetFoo(int index, int value) { ... } 
    int GetFoo(int index) { ... } 

    __declspec(property(propget=GetFoo, propput=SetFoo)) int Foo[]; 
} 

autres que, Earwicker traçait la solution portable, mais il a raison de dire que vous rencontrerez beaucoup de problèmes.

Questions connexes