Jump to content

Nedaudz par savu klasu veidosanu / C++ Builder


nemirst
 Share

Recommended Posts

auto_ptr laikam vektoros lietot ir slikti.

 

Tas nekas, ja vektors satur objektu ar elementiem, kuriem izmers var mainities laika gaita?

Link to comment
Share on other sites

Protams, ka nekas. Uztver vektoru kā parastu masīvu. Tikai ar tādu papildus bonusa fīču, ka šī masīva garums var patvaļīgi mainīties (dinamiskais masīvs). Un parastam masīvam tak ir pie kājas, kas notiek to saturošo objektu memberiem. Vai tur kautkas vairāk, vai mazāk..

Link to comment
Share on other sites

Nelietojot delete, skatos, ka nekur netiek izsaukts apaksklases destruktors, kas ir pareizi. Tagad pameginasu papetit, kapec pareizi nevar destruktoru izsaukt.

Link to comment
Share on other sites

Tu glabā/deleto virsklases tipa pointerus, bet īstenībā tie ir apakšklases tipa objektus? Ja tā, tad virsklases destruktoram obligāti jābūt virtuālam.

Ir viens tāds nerakstīts likums - ja tev ir kaut viena virtuāla metode virsklasē, tad tā destruktoram arī obligāti jābūt virtuālam.

Labots - bubu
Link to comment
Share on other sites

Tu glabā/deleto virsklases tipa pointerus, bet īstenībā tie ir apakšklases tipa objektus? Ja tā, tad virsklases destruktoram obligāti jābūt virtuālam.

Isti nesapratu.. Mana klasee ir definets pointeris uz citu klasi. To pat laikam nesauc par apaksklasi, vienkarsi klasee ir definets citas klases objekts. So citas klases objektu es veidoju savas klases konstruktora ar new operatoru un noradei pieskiru adresi. Savas klases destruktora, savukart, es dzesu ar delete so objektu. Vai tik nav kaut kadas problemas ar vektoru. Jo manas klases objekti tiek ieklauti vektora.

 

 

Seit manas programmas kods:

// Unit1.cpp
std::vector<myclass1>myclass1objvector;

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  myclass1objvector.reserve(3);
  for(int i=0; i<3; i++)
  myclass1objvector.push_back(myclass1());
}

// myclass1.h
class myclass1
{
  public:
  myclass2 *class2obj;

  myclass1()
  {
	 class2obj = new myclass2();
  }
  ~myclass1()
  {
	 delete class2obj;
  }
};

// myclass2.h
class myclass2
{
  public:
  myclass2()
  {
  }
};

Tiek izmesta kluda, kad veru ciet formu jeb, kad tiek izsaukts vektora destruktors un lidz ar to abu klasu destruktori.

 

Pasekoju si koda konstruktoru/destruktoru izsauksanas secibu un ta nav tada ka vajadzetu but. Ta ir sada:

1. objekta konstruktors

1. objekta apaksobjekta konstruktors

1. objekta destruktors

1. objekta apaksobjekta destruktors

2. objekta konstruktors

...

Tatad iznak, ka tiek izveidoti objekti un uzreiz izdzesti. Kapec ta?

 

A, laikam tiek saglabata objekta kopija vektora un push_back parametrs tiek uzreiz izdzests - jeb izsaukts ta destruktors. Tas gan jau normali skaitas.

Labots - nemirst
Link to comment
Share on other sites

Apakšklase ir pavisam kautas cits.

class Apakshklase : Virsklase
{... };

 

Tāda "apaškobjekta" jēdziena vispār nav.

 

Problēma ar taviem class2obj pointeriem ir tāda, ka vektors taisa kopijas taviem objektiem. Tb nedrīkst vektorā likt tipus, kurus nevar normāli kopēt (ar operator = vai copy construktoru).

 

Taču, kas notiek tev - piemēram copy-konstruktorā - tiek izveidots jauns myclass1 objekts. Tam jaunajam objektam tiek piešķirts class2obj pointeris uz to pašu myclass2 objektu, kas vecajā myclass1 objektā. Un tad vēlāk tiek dzēsts ārā šis vecais myclass1 objekts. Un rezultātā jaunajam myclass1 objektam ir invalīds class2obj pointeris, kurš pie tam vēlāk tiek dzēsts ar delete.

 

Implementē copy-konstruktorus un piešķiršanas operatorus klasēm, kurās glabā pointerus, ja gribi lai tās var tikt kopētas.

 

Vai arī - glabā vektorā pointerus uz myclass1 klases objektiem.

Link to comment
Share on other sites

A, laikam tiek saglabata objekta kopija vektora un push_back parametrs tiek uzreiz izdzests - jeb izsaukts ta destruktors. Tas gan jau normali skaitas.

Tapec ari so es piemineju. Nebiju ieprieks iedomajies, ka tiek kaut kas kopets. Tagad skaidrs, kas jadara, paldies.

 

Tavs ieteikums par pointeru glabasanu vektora skiet labaks par copy-constructor ieviesanu. Tada veida izvairos no liekas kopesanas. Sadi daru:

  std::vector<manaklase*>pVector;

  SaktFunkcija()
  {
  manaklase *pObj;	  

  pVector.reserve(skaits);
  for(int i=0; i<skaits; i++)
  {
	 pObj = new manaklase(132);
	 pVector.push_back(pObj);
  }
  }

  BeigtFunkcija()
  {
  for(int i=0; i<skaits; i++)
	 delete pVector[i];
  }

 

Tagad man sagada problemas source/header failu organizesana. Nav nacies laikam veidot programmas ar vairakiem source failiem, turklat vel ar klasem. Builderi projektam ir Unit1.cpp fails un sim failam attiecigais headeris - Unit.h. Es nodeklareju klasi sava headeri - Mans.h. Klase izmanto vairakas savas funkcijas, kuras negribu rakstit ka inline funkcijas - definejot funkcijas klases kermeni. Sis funkcijas modifice definetas formas - Form1(kura defineta Unit1.cpp). Ja funkcijas tiek definetas klases kermeni, tad nav problemu tikt klat formas objektiem, bet, ja defineju tas arpus klases, tad ir problemas, jo izmet kaut kadu kludu runtaimaa. Tapec laikam ir kadas kludas pareizi veidojot savas klases funkcijas vai ieklaujot header failus, vai staistot source failus. Vai funkcijam vajadzetu but definetam .cpp faila? Un varbut var kads vel paskaidrot svarigas nianses organizejot programmas strukturu tiesi mana gadijuma.

Labots - nemirst
Link to comment
Share on other sites

Tur viss ir ļoti vienkārši - C/C++ kompilators neko par .h failiem nezin. Tas kompilē tikai .cpp failus. Visas #include direktīvas tas apstrādā ar parastu copy&paste principu - tb .h failu saturu "iekopē" .cpp failos.

 

Kļūdas runtaimā noteikti nevar rasties no nepareizas .h/cpp failu lietošanas. Ja nu vienīgi tu taisi static globālos mainīgos .h failā, kuru inklūdē vairākos cpp failos un uzskati, ka šis mainīgais būs viens vienīgs eksemplārs programmā (static pie globāla mainīgā/funkcijas nozīmē privātu eksemplāru kompilēšanas vienībā).

 

Ja negribi funkcijas inlainā klases deklarācijā rakstīt, tad neraksti. Taisi tās attiecīgā headerfaila .cpp failā un nav problēmu.

Link to comment
Share on other sites

Man ir Unit1.cpp. Ieklauju savus headerus - class1.h un class2.h. Prieks class1 man nevajag nekadu cpp failu. Bet prieks class2.h es veidoju cpp failu - class2.cpp. class2.cpp es ieklauju failu - class2.h. Projektam pievienoju abus failus - class1.cpp un class2.cpp.

Prieksnojauta saka prieksa, ka class2.h failam jaizskatas sadi:

// class2.h
class class2
{ 
  public:
 class2()
 {
	 Funkcija1();
 };
 int Funkcija1(void);
};

Savukart. class2.cpp sadi:

// class2.cpp
include "class2.h"
int class2::Funkcija1(void)
{
  Form1->Caption = "asdf";   

  return 0;
}

 

Vai tad es pareizi daru?

 

 

 

Hm, ieklavu vel class2.cpp failaa lielo Unit1.h headeri, un aigaja viss ka nakas. Vai tas ir labs veids?

 

Klase class1 deklaracijaa satur objektu no class2, tadel class1.cpp faila es noradu 2 headerus - class1.h, class2.h. Kapec izmet kludu kompilators, uzradot, ka nevar izveidot tada tipa objektu?

 

ieklavu class1.h header failaa headeri class2.h. ta darit ir normali?

Labots - nemirst
Link to comment
Share on other sites

Iekš h faila iekļaut citu h failu ir ļoti normāli.

Bet grūti izsekot tam, ko un kur tu tur iekļauj..

Kapec izmet kludu kompilators, uzradot, ka nevar izveidot tada tipa objektu?
Kādu precīzi kļūdu izmet?
Link to comment
Share on other sites

neatceros jau vairak, bet tagad viss strada, kad esmu ieklavis include failus include failaa. Tagad mani interese sads gadijums:

*src1.cpp fails lieto includi inc1.h

*inc1.h lieto includes a1.h un a2.h

*src1.cpp failam ir nepieciesama gan inc1.h, gan a2.h include

Vai ir normali, ja ieklauju src1.cpp faila tikai inc1.h headeri? Tadejadi, skatoties src1.cpp kodu, es neredzu visas includes, bet man jaskatas vel inc1.h, lai redzetu, ka src1.cpp izmanto ari a2.h includi. Tas man diez ko nepatik. Vai nevar kaut ka ari src1.cpp ieklaut a2.h includi, bet nodrosinaties pret headeru parklasanos? Vai ari ta darit butu greizi un viss ir normali tapat?

 

A, un kluda bija par to, ka neatrod kompilators tadu tipu - manaklase2. manaklase2 objekts man bija definets deklarejot manaklase1(manaklase1.h header failaa). Es ieklavu manaklase2.h failu manaklase1.cpp faila, bet, acimredzot, vajag ieklaut so headeri manaklase1.h faila.

Labots - nemirst
Link to comment
Share on other sites

Tas ir normāli no kompilatora skatupunkta.

Taču parasti pieņemts inkludēt to a2.h failu arī tajā src1.cpp failā. Lai cilvēkam būtu vieglāk redzēt, no kuriem failiem šis konkrētais fails ir atkarīgs.

 

Pret headeru pārklāšanos vienmēr vajag aizsargāties. To dara ar header guard'iem:

#ifndef __MANA_FAILA_VAARDS_H__
#define __MANA_FAILA_VAARDS_H__

... headera saturs

#endif

 

vai arī:

#pragma once

... headera saturs

Tas otrais strādā uz MSVC un GCC. Nezinu par citiem C/C++ kompilatoriem.

Link to comment
Share on other sites

Izveido kontu, vai pieraksties esošajā, lai komentētu

Jums ir jābūt šī foruma biedram, lai varētu komentēt tēmas

Izveidot jaunu kontu

Piereģistrējies un izveido jaunu kontu, tas būs viegli!

Reģistrēt jaunu kontu

Pierakstīties

Jums jau ir konts? Pierakstieties tajā šeit!

Pierakstīties tagad!
 Share

×
×
  • Izveidot jaunu...