klasa ze wskaźnikiem do char

0

Witajcie, mam pewien problem. Oto mój kod, klasa:

class napis
{
 public:
     char *ss;
     int ile;
 public:
     napis(char *arg="");
     friend ostream & operator<<(ostream & wypisz, const napis & n); 
     friend napis operator+(napis n1, napis n2);   
};

takie metody:

 
napis::napis(char *arg)
{
 ss=arg;
 ile=strlen(arg);
}
//------------------------------------------------------------------------------
ostream & operator<<(ostream & wypisz, const napis & n)
{
 wypisz<<n.ss;
 return wypisz;
}
//------------------------------------------------------------------------------
napis operator+(napis n1, napis n2)
{
 napis suma;
 suma.ile=n1.ile+n2.ile;
 char w[suma.ile+1];
 strcpy(w, n1.ss);
 strcat(w, n2.ss);
 suma.ss=w;
 return suma;
}

i mam pewien problem, z operatorem +, nie działa on poprawnie. Tzn do momentu skopiowania do tymczasowej tablicy char w jest ok, problem się zaczyna, gdy przypisuje do suma.ss=w, nie wiem dlaczego? Jedyne co mi przychodzi na myśl to ten konstruktor domniemany przy dekleracji napis suma, tam wpisuje do wskaźnika pusty string...Proszę o rady.

1

w jest tablicą lokalną, która przestaje istnieć po wyjściu z funkcji. wskaźnik przypisywany do suma.ss przestaje być prawidłowy.

Do tego masz w konstruktorze warninga:

     napis(char *arg=""); // warning: deprecated conversion from string constant to 'char*'
1

Po pierwsze ten konstruktor nie jest zbyt dobry. Mogę się założyć, że gdzieś to wszystko Ci się wywali przez odnoszenie się do bloku pamięci, w którym jest zupełnie coś innego niż się spodziewasz.
Np.

napis *xxx;
{
    char cos[] = "blebleble";
    napis = new napis(cos);
}
//i od tego miejsca xxx.ss pokazuje na miejsce w pamięci, w której już nie ma tej tablicy cos

Lepszym rozwiązaniem w konstruktorze będzie coś takiego:

ss = new char[strlen(arg)+1];
strcpy(ss, arg);
ile = strlen(ss);

Drugą sprawą jest operator+: wewnątrz niego tworzysz tablicę w na stosie, a potem jej adres przypisuje do ss - po wyjściu z tego operatora tablica przestaje istnieć. Dodatkowo takie tworzenie tablic raczej nie przejdzie przez każdy kompilator (MSVC++ na coś takiego nie pozwala - chyba że jest jakaś opcja, którą to można włączyć)

0

Dzięki, zawsze zapominam o tym, żeby nie zwracać adresu tablicy lokalnej.
Dodatkowo te char*, na których nigdy nie działałem, z racji tego, że od zawsze używam klasy string.

Mam jeszcze jedno pytanie, czy zdefiniowanie własnego konstruktora kopiującego, który m.in. dynamicznie alokuje pamięć dla składowej ss klasy klasa jest niezbędne? Czy wystarczy mi ten automatycznie generowany przez kompilator? Pytam, bo wydaje mi się, że kk jest niezbędny, ale bez niego również wszystko działa poprawnie.

0

Bez konstruktora kopiującego będzie działać, ale nie tak jak oczekujesz - będzie kopiować wskaźniki, a nie to co jest pod tymi wskaźnikami. Skutkiem tego będzie to, że zmiana w jednym obiekcie, spowoduje zmianę w drugim.

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