Problem z klasą jako argumentem konstruktora.

0

Mam problem z którym nie wiem jak sobie poradzić. Mam za zadanie stworzyć m.in obiekt klasy kolor, który jako nazwę będzie przyjmował obiekt klasy TString. Gdy przekazuje jako argument do jednoargumentowego konstruktora koloru obiekt napis3 typu TString to problem polega na tym, że:

  1. Wydaje mi się, że nie stosując referencji jako napis dla koloru zostają przypisane śmieci, bo po zakończeniu pracy konstruktora kopia argumentu zostaje usunięta, problem w tym że także napis3 zostaje usunięty, co przy zakończeniu działania programu kończy się pojawieniem błędu, ponieważ, jak mi się wydaje, destruktor napisu3 stara się usunąć coś czego już nie ma.
  2. Gdy przekaże argument przez referencje, to co prawda klasa kolor zostanie wypisana poprawianie, jednak po zakończeniu pracy programu destruktor koloru usunie także przekazany przez ans napis 3, wtedy destruktor napisu3 wysypie nam błąd podczas zakończenia pracy programu.
    Czy da się rozwiązać ten problem bez dodawania innych metod?
    Co jeszcze wydaje mi się dziwne, pewnie z powodu braku doswiadczenia, ale gdy przekazuje napis3 jako argument nie wiem dlaczego uruchamia mi się konstruktor bezargumentowy i destruktor TString, za nim jeszcze zostanie wykonana pierwsza instrukcja z konstruktora koloru.
#pragma once
#include <iostream>
#include <conio.h>
#include "kolor.h"
#include "TString.h"
#include "osoba.h"


using namespace std;

int main(){

	TString napis3("czarny");
	kolor *czarny = new kolor(napis3);
	czarny->drukuj();
	delete czarny;
	napis3.drukuj();
	getchar();

} 
 
#pragma once

using namespace std;

class TString
{
private:
	char *str;
	int len;
public:
	TString();
	TString( char *argS );
	TString( char aZ, int ile );
	~TString();
	void drukuj();
};

TString::TString()
{
	len = 1;
	str = new char [len+1];
	strcpy( str, "@" );
	cout<<"Konstruktor bezargumentowy nazwy"<<endl;
}

TString::TString( char * argS )
{
	len = strlen( argS );
	str = new char [len+1];
	strcpy( str, argS );
	cout<<"Konstruktor jednoargumentowy nazwy"<<endl;
}

TString::TString( char aZ, int ile ) 
{
	len = ile;
	str = new char [len+1];
	for( int i=0; i<len; i++ )
		*( str + i ) = aZ;
	*( str + len ) = '\0';
	cout<<"Konstruktor dwuargumentowy nazwy"<<endl;
}

TString::~TString()
{
	if( str != NULL){
		delete [] str;

	}
	cout<<"Destruktor napisu"<<endl;
}

void TString::drukuj(){
	cout<<str<<endl;
}
#pragma once
#include "TString.h"

using namespace std;

class kolor{
      private: 
		  int R;
		  int G;
		  int B;
		  TString nazwa;
	  public:
		  kolor();
		  kolor(TString argstr);
		  kolor(TString &argstr, int argR, int argG, int argB);
		  ~kolor();
		  void drukuj();
};

kolor::kolor():nazwa("biały"){
	R = 255;
	G = 255;
	B = 255;
	cout<<"Konstruktor bezargumentowy koloru"<<endl;
}

kolor::kolor(TString argstr){
	R = 0;
	G = 0;
	B = 0;
	nazwa = argstr;
	cout<<"Konstruktor jednoargumentowy koloru"<<endl;
}

kolor::kolor(TString &argstr, int argR, int argG, int argB){
	R = argR;
	G = argG;
	B = argB;
	nazwa = argstr;
	cout<<"Konstruktor wieloargumentowy koloru"<<endl;
}
kolor::~kolor(){
	cout<<"Destruktor koloru"<<endl;	
}

void kolor::drukuj(){
cout<<R<<G<<B<<endl;
nazwa.drukuj();
} 
0

Masz klasę, która składa się ze wskaźnika i alokuje pamięć a nie napisałeś konstruktora kopiującego i operatora przypisania. Dopisz je, inaczej będą dziać się cuda. To standardowa praktyka...

0

Konstruktor kopiujący jest tylko jeden. W Twoim wypadku będzie to:

TString(const TString &other);
0
 
TString::TString(const TString &tstring){
	str = new char [strlen(tstring.str) + 1];
	len = tstring.len;
	cout<<"konstruktor kopiujący napisu"<<endl;
}

A jak to jest z operatorem przypisania? Też jeden, czy ich ilość zależy od konstruktorów?

0

Wszystko działa, dziękuje za pomoc:)

1

Jest pewien idiom (metoda, sposób) na implementację operatora przypisania "copy and swap" (skopiuj i podmień). Polega ona na oddelegowaniu kompilatorowi wykonania kopii obiektu (w gruncie rzeczy wywołanie naszego konstruktora kopiującego) i później tylko podmianie. Upraszcza to ten operator w wielkim stopniu oraz ułatwia późniejszą implementację move constructor i move assignment operator z C++11.

http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom

0
TString &TString::operator=(const TString &tstring){
        if(this!=&tstring)
            {
             if(str) delete[] str;
             str = new char [tstring.len + 1];
             len = tstring.len;
	  memcpy(str,tstring.str,len+1);
           }
        
        cout<<"operator przypisania"<<endl;
        return *this;
  }
 

Tak może być?? Działa, ale kto wie, jak to jest z wyciekami;]

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