Java toString C ++ eşdeğeri?


151

Bir akışa yazılanları, yani coutözel bir sınıftaki bir nesneyi kontrol etmek istiyorum . Bu C ++ ile mümkün mü? Java'da toString()benzer amaçlarla yöntemi geçersiz kılabilirsiniz .

Yanıtlar:


176

C ++ sen aşırı olabilir operator<<için ostreamve özel sınıfı:

class A {
public:
  int i;
};

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

Bu şekilde sınıfınızın örneklerini akışlara gönderebilirsiniz:

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

Durumda senin operator<<istekler sınıfın iç görün yazdırmak Ave gerçekten de arkadaş fonksiyonu olarak ilan verebilir, özel ve korumalı üyeler erişmesi gerekir:

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
Sınıfın özel üyelerine erişmek için gerekli olabileceğinden, << işlecini sınıfın arkadaş işlevi olarak bildirmek daha iyidir.
Naveen

5
Daha da iyisi friend, onu sınıfın gövdesi içinde ve aynı zamanda - using namespaceişleci (ve sınıfı) içeren ad alanı için yapmak zorunda kalmayacaksınız, ancak ADL bunu sınıfın nesnesi olduğu sürece bulacaktır. işlenenlerden biri.
Pavel Minaev

... yukarıdakilerin " onu sınıfın gövdesi içinde arkadaş olarak tanımla " - bir satır içi üye tanımında olduğu anlamına geliyordu .
Pavel Minaev

2
@fnieto: bu dumpgenel yöntem kirli ve gereksizdir. friendBurada kullanmak gayet iyi. Gereksiz bir yöntem veya müdahaleci tercih edip etmemek friendtamamen bir zevk meselesidir, ancak friendbu kesin amaç için tartışmalı olarak getirilmiştir.
Konrad Rudolph

1
@Pavel: İşleç bağımlı arama, işleç sınıfla aynı ad alanında tanımlandığı sürece yine de bulur. Bunun arkadaşlarla bir ilgisi yoktur ve sınıf içinde bildirilmesi / tanımlanması gerekmez. Ayrıca, operator<<()üye işlevi yapmak işe yaramaz: std::ostreamsol tür işleneni kabul etmesi için onu üye işlevi yapmak zorunda kalırsınız std::ostream.
sth

50

Ayrıca, polimorfizme izin vererek bu şekilde de yapabilirsiniz:

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
Java'nın toStringdavranışını kopyalamak için sanal işlev için +1 .
Konrad Rudolph

Sınıfta doğrudan operatör << belirtmek yerine neden aptal?
monksy

1
beacause sonsuz döngüye ve bir kilitlenmeyi olmasını istemiyoruz
Fernando Nieto - fnieto

1
Belki de bu teknik, neyin seri hale getirileceğine dair seçenekleri geçmek için hızlı ve kolaydır. Aksi takdirde, seçeneklerle ve serileştirilecek verilerle başlatılan başka bir sınıf arkadaşlığı operatörü << tanımlanması gerekir.
Samuel Danielson

Başka bir nokta, döküm işlevselliğinin uygulanmasının, önerilen işleç kullanılarak mümkün olmayan bir arabirim tarafından uygulanabilmesidir.
jupp0r

29

C ++ 11'de, nihayet standarda to_string eklenir.

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


15
Bu, bu sayfaya yararlı bir ektir, ancak C ++ uygulaması Java / C # 'dan önemli ölçüde farklıdır. Bu dillerde, tüm nesnelerin ToString()temel sınıfında tanımlanan sanal bir işlevdir ve bu nedenle herhangi bir nesnenin dize olarak temsilini ifade etmek için standart bir yol olarak kullanılır. Bu işlevler yalnızca yerleşik türler için geçerlidir. C ++ içindeki deyimsel yol, özel türler için işleci geçersiz kılmaktır. std::string<<
Drew Noakes

9
Java'nın operator<<basit Stringanlambilimine kıyasla standart imzanın "çirkinliği", to_string()sadece "yararlı bir ekleme" değil, C ++ 'da bunu yapmanın tercih edilen yeni yoludur. OP tarafından olduğu gibi, bir sınıfın özel bir dize temsili Aisteniyorsa, sadece string to_string(A a)aşağıdaki class Ayeterliliklerin tanımını yazmak gerekir . Bu, Java'daki gibi kalıtımla yayılır ve Java'daki gibi birleştirilebilir (dize ekleyerek). toString()Java'da geçersiz kılmamak zaten sınırlıdır.
P Marecki

10

John'un söylediklerinin bir uzantısı olarak, dize temsilini çıkarmak ve bunu bir saklamak istiyorsanız std::string:

#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::stringstreambulunan <sstream>başlığı.


2
Bu bir serileştirme dizesi elde etmek için saçma bir yol!
Gerd Wagner

9

Soru cevaplandı. Ama somut bir örnek eklemek istedim.

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

Bu örnekte operatörün aşırı yüklenmesi anlaşılmalıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.