Tam Sürümünü Görmek İçin : constructor
quasimodo
10/05/2007, 15:09
class Array {
public:
Array( int = 10 ); // varsayilan constructor
Array( const Array & ); // kopya constructor
~Array(); // yıkıcı
private:
int size; // arrayin uzunlugu
int *ptr; // array ilk elemaninin baslangic adresi
};
Array::Array( int arraySize )
{
size = ( arraySize > 0 ? arraySize : 10 );
ptr = new int[ size ]; // array icin bos alan ayriliyor
assert( ptr != 0 ); // ayrilamazsa sonlandir
for ( int i = 0; i < size; i++ )
ptr[ i ] = 0; // array initialize ediliyor
}
Array::Array( const Array &init ) : size( init.size )
{
ptr = new int[ size ]; // array icin bos alan ayriliyor
assert( ptr != 0 ); // ayrilamazsa sonlandir
for ( int i = 0; i < size; i++ )
ptr[ i ] = init.ptr[ i ]; // kopyalaniyor
}
// Destructor
Array::~Array()
{
delete [] ptr;
}
class imizdan bir nesne olustururken ve buna yapici ile ilk
deger verirken normalde
Array numbers(7);
yapiyorduk ya.
Array numbers = 7;
Bunu bu sekilde yapabilirmiyiz?
Bunu bu sekilde yaptigimizda yine yapici fonksiyon cagirilirmi?
Bunu yapabilmek icin = operatorunu asiri yuklemelimiyiz?
lektroon
10/05/2007, 15:43
Evet yapabilirsin.
Array numbers = 7;
dediginde compiler Array(int = 10) constructor'ini cagirir. Yani implicit type conversion yapar. Ancak eger sen bunun bu sekilde yapilamamasini saglamak istiyorsan, constructor'in onune explicit keyword'unu eklemelisin.
explicit Array(int = 10);
O zaman:
Array numbers = 7; //Invalid
Array numbers(7); //Valid
olur.
acehreli
10/05/2007, 20:09
1) assert( ptr != 0 ); satirinda ptr hicbir zaman 0 olamaz, cunku new'un bellek ayiramamasi durumunda std::bad_alloc hatasi atilir ve o satira zaten gelinemez. (new malloc degildir! :) )
2) Ayrica, assert programcinin kendi kendisini denetlemek icin kullandigi bir aractir. Bellek ayiramamak boyle bir hata olmadigi icin assert uygun degil. Ama hic yoktan iyidir. :)
3) Uc islevler kuralini unutmussun cunku Array'in atama isleci (operator=) tanimlanmamis! Bu kurala gore, eger su uc islevden herhangi birisini yazmissan, hemen hemen her zaman ucunu de en azindan bildirmen gerekir: kopyalayici, atama isleci, ve bozucu islev.
4) lektroon explicit'i zaten anlatmis.
Ek olarak; ben olsam explicit yapardim, cunku int istenen yerlere yanlislikla Array gonderildiginde derleyicinin sessizce kabul etmesi herhalde uygun olmazdi. Cunku soyle bir kullanimda da calisirdi:
void foo(const Array & dizi);
int main()
{
// yanlislik mi, yoksa gercekten uzunlugu 5 olan bir dizi mi istedim?
foo(5);
}
Array kurucusu explicit olursa foo(5) satiri calismaz. Eger gercekten Array istiyorsam bunu acikca ("explicitly") soylemem gerekir:
foo(Array(5)); // cok daha guzel ve "acik"! :)
Ali
quasimodo
11/05/2007, 14:50
Aslinda new de boyle bir denetimin yanlis oldugunu biliyorum
ama hata yakalama konusunu ogrenene kadar sanirim
bu sekilde kullanicam.
Array numbers = 7;
Bu sekilde cagirilmasini kurucu fonksiyonu
private yaparak engelleyebilirmiyim?
Yoksa kurucu fonksiyonu private yaptigim zaman
sadece
Array numbers = Array(5);
sekilde yapılmasi mi engellenmis olur???
acehreli
11/05/2007, 21:03
1) Hata yakalama ile ilgili cok temel bir seyi ogrendigin zaman, o assert'teki ptr'in hicbir zaman 0 olmayacagini anlayacaksin. Yani o assert satirini yazmanin bir anlami yok, cunku o satir her zaman dogru calisacak.
Hata yakalama ile ilgili cok temel bir seyi ogrenecegin zaman iste bu zaman: :) new sirasinda hata atilirsa, o hatanin atildigi noktadan sonra hicbir islem isletilmez. Her bir kod kapsami teker teker terk edilir ve atilan hatanin turune uygun bir catch aranir.
Ozetle:
ptr = new int[ size ]; // eger burada hata atilirsa,
assert( ptr != 0 ); // bu satir isletilmez bile
Programin akisi o iki satiri kapsayan blogun disina cikar. (O bloktaki otomatik nesneler sonlandirildiktan sonra.)
Hata atma konusunda yeterli bilgiyi aldin; onun icin oradaki assert'in hicbir ise yaramadigini goruyorsun. :)
Bu arada, new iki nedenle hata atabilir:
- kendisi bellek ayiramazsa std::bad_alloc atilir,
- kurmakta oldugu nesnenin kurucusu hata atarsa, o hata atilir.
Eger assert satirini kullanmakta israrliysan, yani new'un malloc gibi davranmasini istiyorsan, o zaman o sekilde davranan new'u acikca kullanman gerekiyor:
ptr = new (nothrow) int[ size ]; // artik hata atmaz, bellek bulamazsa 0 dOndUrur
assert( ptr != 0 ); // bu satir isletilir
Ama nothrow ancak new'un bellek ayiramadiginda attigi hatayi durdurur. Kurdugu nesnenin kurucusunun attigi hatalar yine bu kapsamdan hemen cikilmasina neden olur.
2) Kurucuyu private yaparsan, o nesneyi yalnizca o sinifin bir islevi veya o sinifin friend'leri kurabilir. Degisen bir sey yok yani. private, yalnizca erisimi belirler.
Array numbers = Array(5);
kullaniminin engellenmesini explicit anahtar sozcuguyle ilgili olarak konusmustuk... (C++'in karisik oldugunu soylemistik degil mi. :D)
Ali
Forum Yazılımı : vBulletin v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.