Constructori

Intrebari despre limbajul C++, standardul C++, STL, OOP in C++ sau alte subiecte nelegate de VisualC++
Post Reply
saneadumb
Junior
Junior
Posts: 4
Joined: 09 Nov 2012, 13:24
Judet: Bucureşti

Constructori

Post by saneadumb » 09 Nov 2012, 13:30

Help plz!!!!
Ajutatima sa fac programul dat!!!
Alocare dinamica!!

Să se creeze clasa String – şir, utilizînd memoria dinamică. Să se definească constructorii: implicit, de copiere şi cu un parametru – pointer spre un şir de tip char. Să se definească funcţiile de atribuire a unui şir la altul, de comparaţie, de căutare a unui subşir, de numărare a simbolurilor ş. a.

Code: Select all

class String{
char *num;
public:
String(); // constructor implicit
String(const String&); // constructor de copiere
String(const char*); // constructor pointer spre un sir de tip char
};
Last edited by saneadumb on 09 Nov 2012, 17:05, edited 1 time in total.



Viorel
Microsoft MVP
Microsoft MVP
Posts: 292
Joined: 13 Jul 2007, 12:26

Re: Constructori

Post by Viorel » 09 Nov 2012, 13:45

Constructorul implicit e cam așa:

Code: Select all

String::String()
{
    num = 0;
}
Restul depind de modul de alocare. Ce fel de alocare dinamică a memoriei ai studiat?

saneadumb
Junior
Junior
Posts: 4
Joined: 09 Nov 2012, 13:24
Judet: Bucureşti

Re: Constructori

Post by saneadumb » 09 Nov 2012, 19:09

Alocarea dinamica a memoriei

saneadumb
Junior
Junior
Posts: 4
Joined: 09 Nov 2012, 13:24
Judet: Bucureşti

Re: Constructori

Post by saneadumb » 09 Nov 2012, 19:09

help plzzzzzzzzzzzzzzzzzzzzzzz

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Constructori

Post by Ovidiu Cucu » 09 Nov 2012, 21:18

Tema pentru acasa? Facem si din astea, daca vedem ca pui si tu umarul un pic mai mult decat sa enunti problema si sa spui "help plzzzzzzzzzzzzzzzzzzzzzzz".
Arunca te rog un ochi la raspunsul la intrebarea "Pot posta in forum tema mea pentru acasa?" si dupa aia poate mai discutam.

User avatar
Marius Bancila
Fondator
Fondator
Posts: 2344
Joined: 11 Jul 2007, 11:45
Judet: Timiş
Location: Timisoara
Contact:

Re: Constructori

Post by Marius Bancila » 09 Nov 2012, 22:47

Daca ai memorie alocata dinamic, ar trebui sa ai si un operator= suprascris. Altfel o sa ai parte de shallow copy cand faci atribuire intre doua obiecte de acelasi fel.

Si ca sa invete si profesorul tau ceva, in C++11 definim si constructorul de mutare si operatorul= de mutare:

Code: Select all

class String 
{
public:
  String(const String&& cpy);
  String& operator=(String&& cpy);
};
http://msdn.microsoft.com/en-us/library/dd293665.aspx
http://www.cprogramming.com/c++11/rvalu ... c++11.html
Marius Bancila
Fondator Codexpert, Microsoft MVP VC++
Site personal | Blog

User avatar
cristianamarie
Membru++
Membru++
Posts: 480
Joined: 12 Mar 2009, 18:47
Judet: Iaşi
Location: Iasi

Re: Constructori

Post by cristianamarie » 10 Nov 2012, 09:06

Vezi ca e o clasa integer intr-un reply de-al meu de mai demult. Modifica pentru char* sau ce vrei tu si mai ai de facut new si delete la constructorii de initializare/copiere si la operatorul =.
Nuclear launch detected

saneadumb
Junior
Junior
Posts: 4
Joined: 09 Nov 2012, 13:24
Judet: Bucureşti

Re: Constructori

Post by saneadumb » 21 Nov 2012, 01:03

Si cum il duc pin la capat mai corect?

Code: Select all


//?) Sa se creeze clasa String – sir, utilizind memoria dinamica. 
//Sa se defineasca constructorii: 
//implicit, 
//de copiere si 
//cu un parametru 
//– pointer spre un sir de tip char. 
//Sa se defineasca 
//functiile de atribuire a unui sir la altul, 
//de comparatie, 
//de cautare a unui subsir, 
//de numarare a simbolurilor s. a.
#include<iostream>
#include<cstring>
using namespace std;
class String {
private:
	char *num;
public:
	String()
 { cout<<"Constructorul implicit"<<endl;
    num=NULL; 
 
 } // constructor implicit
    

  
    String(const String& obj) 
{cout<<"Constructor de copiere"<<endl;
	num = new char[strlen(obj.num)+1]; 
strcpy(num, obj.num); // constructor de copiere
}
    
    String( char* nm)
{cout<<"Constructor de conversie"<<endl;
	num = new char[strlen(nm)+1];
	strcpy(num, nm);
} // constructor pointer spre un sir de tip char

void atribuire(String& s)
{ num = new char[strlen(s.num)+1]; 
     strcpy(num,s.num);   //functia atribuire;  
}
	
int compar(String& s) //functia comparare 
{
return strcmp(num,s.num);
}

char* caut(String& s) //cautarea unui subsir
{
return strstr(num,s.num);
}

int numarare(String& s) //numararea simbolurilor
{
return strlen(s.num);
}
void show()
{cout<<num<<endl;
     }
};
int main()
{
String s, s1("Buna ziua"), s2(s1);

cout<<"Afisarea continutului obiectului creat de constructorul implicit"<<endl;
cout<<"s=";
s.show();

cout<<"Afisarea continutului obiectului creat de constructorul conversie"<<endl;
cout<<"s=";
s1.show();

cout<<"Afisarea continutului obiectului creat de constructorul de copire"<<endl;
cout<<"s=";
s2.show();

system("Pause>>void");
return 0;

}





User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Constructori

Post by Ovidiu Cucu » 21 Nov 2012, 15:55

Cateva observatii, la o prima aruncatura de ochi:
  1. In primul rand si cel mai naspa, nu tii nicaieri cont daca pointerii is NULL (nici String::num, nici pe cei care-i pasezi ca argumente). Daca pasezi un pointer NULL unei functii CRT (din biblioteca C) sau lui std::cout, poti sa zici mersi daca programelul crapa cu strigaturi si n-o ia prin alte balarii mai nasoale.
  2. Nu ai implemetat destructorul. Cine vrei sa faca curatenie?
  3. Nu dezaloci inaite de a face realocari (vezi in functia String::atribuire). Pentru curatenie, ar fi bine sa faci o functie care sa dea delete la buffer si-apoi sa puna pointerul pe NULL, pe care sa o apelezi de peste tot unde-i nevoie.
  4. In momentul cand faci constructorul de copiere, primul gand pe care trebuie sa-l ai este sa supraincarci si operatorul de atribuire corespunzator.
    Un progamator de C++ (nu unul de Java) vrea, daca poate scrie...

    Code: Select all

       String s1("Bau!");
       String s2 = s1; // <-- se apeleaza constructorul de copiere.
    ...sa scrie si:

    Code: Select all

       String s1("Bau!");
       String s2;
       s2 = s1; // <-- se apeleaza operatorul de atribuire.
    La fel si in cazul celuilalt constructor (caruia i-ai zis "de conversie").
    Daca pot scrie:

    Code: Select all

       String s1 = "Bau!" // <-- se apeleaza constructorul care primeste const char*
    ma astept sa scriu si:

    Code: Select all

       String s1;
       s1 = "Bau!"; // <-- se apeleaza operatorul de atribuire care primeste const char*
  5. Functia show nu are ce cauta in clasa String. Nu-i treaba unui string/text sa "se afiseze". Ce te faci daca vrei sa-l afisezi in alta parte decat in consola sau nu vrei sa folosesti STL? Mai bine, pui o metoda, sa-i zicem String::GetString, care sa-ti intoarca un pointer la buffer pe care poti sa-l pasezi mai departe, sa zicem la std::cout. Si/sau, ca sa nu te doara mana mai departe tot scriind "s.GetString()", poti implementa un operator de conversie (cast) la const char*.
  6. Scoate cout-urile de prin metodele lui String. Stiu, le-ai pus acolo cu scop de debug insa mai bine obisnuieste-te sa pui breakpoint(s) si sa rulezi pas cu pas sa vezi ce de intampla. In plus poti, defini (daca n-ai deja la dispozitie) niste macro-uri de TRACE care sa scuipa informatii in consola numai in modul DEBUG si care sa nu fie dependente de STL.
  7. O observatie de forma: incearca sa scrii codul cat mai ordonat, cu fiecare instructiune in randul ei. Nu ajuta cu nimic daca le ingramadesti dupa acolade sau daca pui acolada dupa numele clasei si sa strici identarile. Dimpotriva, e mai greu de citit.
  8. Si-or mai fi...

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Constructori

Post by Ovidiu Cucu » 21 Nov 2012, 19:43

O mica completare la punctul #4. Daca nu definesti constructourul de copiere sau nu supraincarci operatorul de atribuire, compilatorul face copiere default, membru cu membru (memberwise copy). Daca clasa contine pointeri pentru care se face alocare dinamica (cum este cazul nostru) nu-i OK. In concluzie, in clasa String este obligatoriu atat sa definesti constructorul de copiere, cat si supraincarci operatorul de atribuire.

In fine, ca punct de pornire, uite un exemplu simplu si scolaresc de clasa String.

Code: Select all

class String
{
// Data
private:
   char* m_pBuffer;
// Constructors
public:
   String();
   String(const String& ref);
   String(const char* pBuffer);
   // ...
// Destructor
public:
   ~String();
// Operators
public:
   String& operator=(const String& ref);
   String& operator=(const char* pBuffer);
   operator const char*() const;
   // ...
// Public
public:
   void Copy(const String& ref);
   void Copy(const char* pBuffer);
   void Empty();
   bool IsNull() const;
   size_t GetSize() const;
   const char* GetString() const;
   // ...
// Implementation
private:
   // ...
};
Unde vezi puncte-puncte, ai de copmpletat. Iata si implementarea metodelor (de notat ca unele dintre ele le poti pune inline).

Code: Select all

#include <stdio.h>
#include <string.h>

#if defined(DEBUG) || defined(_DEBUG)
#define TRACE(x) printf(x)
#else
#define TRACE(x)
#endif

// constructor implicit
String::String() : m_pBuffer(NULL)
{
   TRACE("String::String()");
}

// constructor de copiere
String::String(const String& ref) : m_pBuffer(NULL)
{
   TRACE("String::String(const String& ref)");
   Copy(ref);
}

// constructor care primeste const char*
String::String(const char* pBuffer) : m_pBuffer(NULL)
{
   TRACE("String::String(const char* pBuffer)");
   Copy(pBuffer);
}
// destructor
String::~String()
{
   Empty();
}

// operator de atribuire
String& String::operator=(const String& ref)
{
   TRACE("String& String::operator=(const String& ref)");
   Copy(ref);
   return *this;
}

// operator de atribuire
String& String::operator=(const char* pBuffer)
{
   TRACE("String& String::operator=(const char* pBuffer)");
   Copy(pBuffer);
   return *this;
}
// operator de conversie (cast) la const char*
String::operator const char*()const
{
   return GetString();
}
// copie un string 
void String::Copy(const String& ref)
{
   if(this != &ref)
   {
      Empty();
      size_t size = ref.GetSize();
      if(size > 0)
      {
         m_pBuffer = new char[size + 1];
         strcpy(m_pBuffer, ref.m_pBuffer);
      }
   }
}
// copie un buffer
void String::Copy(const char* pBuffer)
{
   Empty();
   if(NULL != pBuffer)
   {
      size_t size = strlen(pBuffer);
      m_pBuffer = new char[size + 1];
      strcpy(m_pBuffer, pBuffer);
   }
}
// dezaloca bufferul
void String::Empty()
{
   delete []m_pBuffer;
   m_pBuffer = NULL;
}
// intoarce true daca bufferul e NULL
bool String::IsNull() const
{
   return NULL == m_pBuffer;
}
// intoarce numarul de caractere din buffer (fara teminatorul NUL)
size_t String::GetSize() const
{
   return IsNull() ? 0 : strlen(m_pBuffer);
}
// intoarce pointer la buffer sau un string empty in caz de NULL
const char* String::GetString() const
{
   return IsNull() ? "" : m_pBuffer;
}
E departe de a fi o clasa String "profesionala" insa e buna cu scop didactic, ca sa te familiarizezi cu constructorii, operatorii, alocarile etc.
Arunca te rog mai intai un ochi la observatiile din postarea mea anterioara apoi incearca sa intelegi ce si cum am facut aici. Ce nu-i clar, te rog intraba. Nu ma supar nici daca-mi gasesti erori sau chestii pecare nu le-am facut asa cum trebuie. ;)
In cele din urma, incearca sa completezi cu ce mai este nevoie. Iarasi, poti posta pe forum sa vedem ce faci bine si ce nu.

Post Reply