166 votes

L'équivalent en C++ du toString de Java ?

J'aimerais contrôler ce qui est écrit dans un flux, c'est-à-dire cout pour un objet d'une classe personnalisée. Est-ce possible en C++ ? En Java, vous pourriez surcharger la fonction toString() à des fins similaires.

192voto

sth Points 91594

En C++, vous pouvez surcharger operator<< para ostream et votre classe personnalisée :

class A {
public:
  int i;
};

std::ostream& operator<<(std::ostream &strm, const A &a) {
  return strm << "A(" << a.i << ")";
}

De cette façon, vous pouvez produire des instances de votre classe sur des flux :

A x = ...;
std::cout << x << std::endl;

Au cas où votre operator<< veut imprimer les données internes de la classe A et a réellement besoin d'accéder à ses membres privés et protégés, vous pouvez également la déclarer comme une fonction amie :

class A {
private:
  friend std::ostream& operator<<(std::ostream&, const A&);
  int j;
};

std::ostream& operator<<(std::ostream &strm, const A &a) {
  return strm << "A(" << a.j << ")";
}

19 votes

Il est préférable de déclarer l'opérateur<< en tant que fonction amie de la classe car il pourrait être nécessaire d'accéder aux membres privés de la classe.

5 votes

Mieux encore, déclarez-le comme friend et aussi à l'intérieur du corps de la classe - ainsi, vous n'aurez pas à faire using namespace pour l'espace de nom contenant l'opérateur (et la classe), mais ADL le trouvera tant que l'objet de cette classe est un des opérandes.

0 votes

... ce qui précède était destiné à dire " définir comme ami à l'intérieur du corps de la classe" - comme dans, une définition de membre en ligne.

54voto

Vous pouvez aussi le faire de cette façon, en autorisant le polymorphisme :

class Base {
public:
   virtual std::ostream& dump(std::ostream& o) const {
      return o << "Base: " << b << "; ";
   }
private:
  int b;
};

class Derived : public Base {
public:
   virtual std::ostream& dump(std::ostream& o) const {
      return o << "Derived: " << d << "; ";
   }
private:
   int d;
}

std::ostream& operator<<(std::ostream& o, const Base& b) { return b.dump(o); }

4 votes

+1 pour les fonctions virtuelles, afin de copier l'approche de Java. toString comportement.

0 votes

Pourquoi être muet plutôt que de spécifier directement l'opérateur<< dans la classe ?

1 votes

Parce que vous ne voulez pas avoir une boucle infinie et une panne.

31voto

zzj Points 81

Dans C++11, to_string est enfin ajouté à la norme.

http://en.cppreference.com/w/cpp/string/basic_string/to_string

16 votes

Il s'agit d'un ajout utile à cette page, mais l'implémentation en C++ est sensiblement différente de celle en Java/C#. Dans ces langages, ToString() est une fonction virtuelle définie sur la classe de base de todo et est donc utilisé comme un moyen standard d'exprimer une représentation en chaîne de caractères de tout objet. Ces fonctions sur std::string ne s'appliquent qu'aux types intégrés. La méthode idiomatique en C++ consiste à surcharger la fonction << pour les types personnalisés.

11 votes

La " laideur " de la signature standard de operator<< par rapport à une simple String sémantique de Java m'incite à remarquer, que to_string() n'est pas seulement "un ajout utile", mais la nouvelle façon préférée de le faire en C++. Si, comme dans le cas du PO, une représentation de chaîne personnalisée d'une classe A est souhaité, il suffit d'écrire un string to_string(A a) ci-dessous la définition de class A suffit. Cela se propage avec l'héritage comme en Java, et peut être combiné (par addition de chaînes) comme en Java. Non-overriden toString() en Java est de toute façon d'une utilité limitée.

11voto

blwy10 Points 2858

Dans le prolongement de ce que John a dit, si vous voulez extraire la représentation de la chaîne de caractères et la stocker dans un fichier de type std::string faites-le :

#include <sstream>    
// ...
// Suppose a class A
A a;
std::stringstream sstream;
sstream << a;
std::string s = sstream.str(); // or you could use sstream >> s but that would skip out whitespace

std::stringstream est situé dans le <sstream> en-tête.

2 votes

C'est une façon ridicule et encombrante d'obtenir une chaîne de sérialisation !

9voto

La question a trouvé une réponse. Mais je voulais ajouter un exemple concret.

class Point{

public:
      Point(int theX, int theY) :x(theX), y(theY)
      {}
      // Print the object
      friend ostream& operator <<(ostream& outputStream, const Point& p);
private:
      int x;
      int y;
};

ostream& operator <<(ostream& outputStream, const Point& p){
       int posX = p.x;
       int posY = p.y;

       outputStream << "x="<<posX<<","<<"y="<<posY;
      return outputStream;
}

Cet exemple nécessite de comprendre la surcharge des opérateurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X