C ++ setara dengan toString Java?


151

Saya ingin mengontrol apa yang ditulis ke aliran, yaitu cout, untuk objek kelas kustom. Apakah itu mungkin di C ++? Di Jawa Anda bisa mengganti toString()metode untuk tujuan yang sama.

Jawaban:


176

Di C ++ Anda dapat kelebihan operator<<untuk ostreamdan kelas khusus Anda:

class A {
public:
  int i;
};

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

Dengan cara ini Anda dapat menampilkan instance kelas Anda di stream:

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

Jika Anda operator<<ingin mencetak internal kelas Adan benar-benar membutuhkan akses ke anggota pribadi dan terlindungi, Anda juga dapat mendeklarasikannya sebagai fungsi teman:

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

16
Lebih baik menyatakan operator << sebagai fungsi teman kelas karena mungkin diperlukan untuk mengakses anggota pribadi kelas.
— Naveen

5
Lebih baik mendeklarasikannya sebagai friend, dan juga di dalam tubuh kelas - dengan itu, Anda tidak harus melakukan using namespaceuntuk namespace yang berisi operator (dan kelas), tetapi ADL akan menemukannya selama objek kelas itu adalah salah satu operan.
— Pavel Minaev

... di atas dimaksudkan untuk mengatakan " mendefinisikannya sebagai teman di dalam tubuh kelas" - seperti dalam, definisi anggota inline.
— Pavel Minaev

2
@ Fieto: dumpmetode publik itu kotor dan tidak perlu. Penggunaan di friendsini baik-baik saja. Apakah Anda lebih suka metode yang berlebihan atau intrusif friendsepenuhnya adalah masalah selera, meskipun friendmungkin telah diperkenalkan untuk tujuan yang tepat ini.
— Konrad Rudolph

1
@Pavel: Pencarian bergantung argumen akan tetap menemukannya, selama operator didefinisikan dalam namespace yang sama dengan kelas. Ini tidak ada hubungannya dengan teman dan tidak perlu dideklarasikan / didefinisikan di dalam kelas. Juga, membuat operator<<()fungsi anggota tidak akan berfungsi: Anda harus menjadikannya fungsi anggota std::ostreamagar dapat menerima operan tipe tangan kiri std::ostream.
— sth

50

Anda juga dapat melakukannya dengan cara ini, memungkinkan polimorfisme:

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

3
+1 untuk fungsi virtual, untuk menyalin toStringperilaku Java .
— Konrad Rudolph

Mengapa bodoh daripada langsung menentukan operator << di kelas?
— monksy

1
karena Anda tidak ingin memiliki loop tak terbatas dan crash
— fnieto - Fernando Nieto

1
Mungkin teknik ini cepat dan mudah untuk melewatkan opsi tentang apa yang akan diserialisasi. Kalau tidak, akan diperlukan untuk menentukan operator teman kelas lain << yang diinisialisasi dengan opsi dan data untuk diserialisasi.
— Samuel Danielson

Poin lain adalah bahwa implementasi fungsionalitas dump dapat ditegakkan oleh antarmuka, yang tidak akan mungkin menggunakan operator yang diusulkan.
— jupp0r

29

Dalam C ++ 11, to_string akhirnya ditambahkan ke standar.

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


15
Ini adalah tambahan yang berguna untuk halaman ini, namun implementasi C ++ berbeda secara signifikan dengan yang ada di Java / C #. Dalam bahasa-bahasa tersebut, ToString()adalah fungsi virtual yang didefinisikan pada kelas dasar dari semua objek, dan karenanya digunakan sebagai cara standar untuk mengekspresikan representasi string dari objek apa pun. Fungsi-fungsi ini std::stringhanya berlaku untuk tipe bawaan. Cara idiomatis dalam C ++ adalah menimpa <<operator untuk tipe kustom.
— Drew Noakes

9
"Keburukan" tanda tangan standar operator<<, dibandingkan dengan Stringsemantik sederhana Jawa mendorong saya untuk berkomentar, itu to_string()bukan hanya "tambahan yang berguna", tetapi cara baru yang disukai untuk melakukannya di C ++. Jika, seperti oleh OP, representasi string kustom dari sebuah kelas Adiinginkan, cukup tuliskan string to_string(A a)definisi class Asuffi di bawah ini . Ini menyebar dengan pewarisan seperti di Jawa, dan dapat dikombinasikan (dengan penambahan string) seperti di Jawa. Lagipula Non-override toString()di Jawa penggunaannya terbatas.
— P Marecki

10

Sebagai perpanjangan dari apa yang dikatakan John, jika Anda ingin mengekstraksi representasi string dan menyimpannya di std::stringlakukan ini:

#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::stringstreamterletak di <sstream>tajuk.


2
Itu cara rumit konyol untuk mendapatkan string serialisasi!
— Gerd Wagner

9

Pertanyaan telah dijawab Tetapi saya ingin menambahkan contoh konkret.

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

Contoh ini membutuhkan pemahaman operator yang berlebihan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.