stringstream utrudnia ludziom życie.

0

Mam taki sobie kod:

 
#include <iostream>
#include <sstream>
#include <vector>

class KlasaA {
    
  std::stringstream ss;
  
  public:
      
      KlasaA() {}
      
//      //konstruktor kopiujący
//      KlasaA(const KlasaA & objA) {
//          this->operator=(objA);
//      }
//      
//      //operator przypisania
//      KlasaA & operator=(const KlasaA & clsA) {
//          this->ss.clear();
//          this->ss << clsA.ss;
//          return (*this);
//      }
      
};

using namespace std;

/*
 * 
 */

int main(int argc, char** argv) {
    
    KlasaA objA;
    
    std::vector<KlasaA> array;
    array.push_back(objA);
    
    char z;
    std::cin >> z;
    
    return 0;
}

Problem tkwi w kopiowaniu przez wartość obiektu klasy który zawiera obiekt klasy stringstream. Gdy dajemy push_back gdy chcemy dodać jakiś element do wektora to kompilator wywala błąd ponieważ:
kompilator generuje dla klasy "KlasaA" domniemany operator przypisania który kopiuje składnik po składniku. Jak wiadomo oczywiście to jak zrobimy tak:

    std::stringstream sss;
    std::stringstream sss2("ala ma 2 koty");
    sss = sss2;
 

to program nie zadziała. Tak jak powyżej prawdopodobnie postąpi kompilator gdy będziemy chcieli przypisać do jednego obiektu klasy "KlasaA" drugi obiekt "KlasaA" czyli dlatego właśnie się wywala bo we metodzie push_back prawdopodobnie będzie się znajdować operacja przypisania obiektów klasy "KlasaA". Ja wykombinowałem sobie tak ,że zdefiniowałem własny operator przypisania oraz konstruktor kopiujący. Jak od komentujemy funkcje operatora przypisania oraz konstruktor kopiujący to program zadziała poprawnie gdyż kompilator będzie wiedział ,że jak chcemy przypisać jeden obiekt "KlasaA" do drugiego nie postąpi tak jak w kodzie powyżej ze przypisaniem jednego stringstreama do drugiego tylko uruchomi moją wersję operatora przypisania. Moje pytanie brzmi:
Dlaczego klasa stringstream nie ma zdefiniowanego operatora przypisania oraz konstruktora kopiującego(nawet jak ma to nie działą on prawidłowo)? Jak będziemy chcieli dodać do wektora jakiś obiekt który zawiera obiekt klasy stringstream przez wartość to będziemy musieli zawsze definiować własny operator przypisania i konstruktor kopiujący?? Czy to nie jest utrudnianie ludziom życia?. Można to jeszcze jakoś inaczej obejść? Nie wiem czy moje rozumowanie jest prawidłowe może program wywala się przez coś innego

5
robcio napisał(a):

Dlaczego klasa stringstream nie ma zdefiniowanego operatora przypisania oraz konstruktora kopiującego(nawet jak ma to nie działą on prawidłowo)?

stringstream wywodzi się z ios_base, która posiada konstruktor kopiujący oraz operator przypisania zadeklarowany w sekcji private przez co klasa ios_base jak i jej klasy pochodne nie są "kopiowalne".

private:
  ios_base (const ios_base&);
  ios_base& operator= (const ios_base&);

Odpowiedz sobie na jedno pytanie: jaki jest sens kopiować strumień?

Chyba nie rozumiesz do końca idei strumieni. Strumienie są obiektami, przez które dane tylko "przechodzą", "płyną". Nie zawierają same w sobie danych, nie przechowują ich, więc nie ma sensu ich kopiować. Jaki byłby sens kopiowania cout albo cin ? Tak naprawdę klasy, które dziedziczą po ios_base odpowiadają tylko za formatowanie danych (co nie jest i tak do końca prawdą ponieważ w rzeczywistości operacje formatujące dane znajdują się w bibliotece 'locale', a więc w zasadzie przechowują tylko informacje o formatowaniu oraz stanie strumienia). Obsługą danych (odczytem czy zapisem) zajmują się w rzeczywistości bufory strumieni, a nie same strumienie. Niestety ale próby kopiowania czy tworzenia kolekcji strumieni świadczą o niezrozumieniu tematu i ewentualnych błędach projektowych. Jak to obejść? Nie próbować tego obchodzić tylko dostosować się do interfejsu jaki oferuje STL.

pozdrawiam

1

sss.str(sss2.str())

0

Chociaż na upartego wszystko się da tak ja zrobiłem to z tym operatorem przypisania i konstruktorem kopiującym mojej klasy. Można by było w sumie jeszcze trzymać obiekty tej klasy w liście wtedy nie było by potrzebne kopiowanie.

0

Odpowiedz sobie na jedno pytanie: jaki jest sens kopiować strumień?

Sensu może i nie ma, ale może być sens umieszczać strumień w klasie, a na pewno jest sens dodawać obiekty do vectora.
A użycie push_back wiąże się z wywołaniem konstruktora kopiującego (lub przesuwającego, jeśli zdefiniowano).

No cóż, C++ nie jest językiem, który ma ułatwiać programiście życie…

1 użytkowników online, w tym zalogowanych: 0, gości: 1