PDA

Tam Sürümünü Görmek İçin : Üye Fonksiyon


Arkantos
22/12/2004, 18:36
Şöyle bir kodumuz var:


#include <iostream>
using namespace std;

class Karmasik
{
public:
Karmasik (double reel, double sanal = 1)
: reel_ (reel), sanal_ (sanal)
{}
Karmasik operator+ (const Karmasik & ) const;
void Yazdir () const;
private:
double reel_, sanal_;
};

Karmasik Karmasik::operator+ (const Karmasik & ikinci) const
{
double reelyeni, sanalyeni;
reelyeni = reel_ + ikinci.reel_;
sanalyeni = sanal_ + ikinci.sanal_;
return Karmasik (reelyeni, sanalyeni);
}

void Karmasik::Yazdir () const
{
cout << "reel =" << reel_ << "sanal" << sanal_;
}

int main()
{
Karmasik ilk (1, 1), ikinci (2, 2), ucuncu;
ucuncu = ilk + ikinci;
ucuncu.Yazdir ();
return 0;
}



Şimdi soru şu buradaki void Yazdir () const; üye fonksiyonunu const yapmamak çok ciddi bir hata mıdır? Eğer hataysa sebepleri nedir? Normalde const olan üye işlevlerin nesnenin durumunda değişiklik yapmayacağına söz verdiğini biliyoruz ama bu dönüş türü void olan bir üye işlev için de geçerlimidir?
Yani ben genelde incelediğim kodlarda void Yazdir () const; yerine void Yazdir() şeklinde gördüm ve bundan pek emin olamadım.


Volkan Uzun
22/12/2004, 18:39
syntax hatasi olmadigini dusunuyorum, ama geriye deger donmedigi halde, sdegisiklik yapabilir dimi ? kodu okurken buyuk rahatlik getiriyor ama onun disindaki artisi eksisini bilmiyorum

acehreli
22/12/2004, 19:10
Eger 'const' olmazsa, sabit nesneleri yazdiramayiz:


Karmasik k0;
Karmasik const k1;

void foo(Karmasik const & k)
{
k.yazdir();
}

// Daha sonra

k0.yazdir(); // Tamam
k1.yazdir(); // HATA
foo(k0); // HATA
foo(k1); // HATA


Arkantos, islevin sonundaki 'const'in dondurulen nesne ile bir ilgisi yok tabii ki. O const, islevin icine girdigimiz anda uzerinde calismaya basladigimiz nesnenin this'ini 'const' yapiyor.

Ayrica, operator+ islevini uye islev degil de serbest islev yaparsan daha hosuna gidecegini dusunuyorum:


Karmasik operator+ (const Karmasik & birinci,
const Karmasik & ikinci)
{
Karmasik sonuc(birinci);
sonuc += ikinci;
return sonuc;
}


Tabii onun calisabilmesi icin simdi bir uye operator+= tanimlaman gerek:


Karmasik & Karmasik::operator+= (const Karmasik & diger)
{
reel_ += diger.reel_;
sanal_ += diger.sanal_;
return *this;
}


Boyle yapinca, arttirma mantigi operator+= isleci icine yazilmis oluyor. Serbest operator+ islevini ise arttirma mantigindan bagimsiz olarak yaziyoruz. Bu yontemi *=, /=, vs. gibi isleclere de uygulayabilirsin.

Ali

Arkantos
22/12/2004, 20:12
Teşekkürler. Çok yardımcı oldu gerçekten. Ama bu başka birisinin yazdığı bir koddu ve bu kodda ucuncu = ilk + ikinci; şeklinde bir toplama yapacaksak diye düşünmüştüm. Yani Karmasik const k1, k2; şeklinde bir nesnemiz olsaydı bunları birbirleriyle de toplayamazdık değil mi? Demek istediğim ben nasıl olsa toplama yapacağına göre const bir Karmasik nesnesi kullanmayacak ve bu yüzden de o void işlevinin sonunda const olmasına gerek yok diye düşünmüştüm.

acehreli
23/12/2004, 00:08
Ilk yazdigin operator+ islevi "const degildi". Onu ele alalim...

Eger elimizde const olan bir nesne varsa:

Karmasik const sabit;
Karmasik degisken;

onu toplama islecinin sol tarafina yazamazdik:

Karmasik sonuc = sabit + degisken;

Cunku o ifade aslinda sunun esdegeridir (ve hatta boyle bile kod icinde yazilabilir):

Karmasik sonuc = sabit.operator+(degisken);

Bu da hata verirdi; cunku operator+ 'const' olmadigi icin, const olan sabit adli nesne "uzerinde isletilemezdi".

Gordugun gibi, operatar+, 'const' olan bir nesne kullanmaya calismis oldu. Ya da ben seni anlamiyorum... :)

Ali

acehreli
23/12/2004, 00:15
Biraz kafam karismis. Burada gonderdigin kodlarda const olmayan bir operator+ yok. Yine de, son yazdigin paragraf icinde toplama isleminden bahsettigin icin bundan bahsettigimi varsaymisim. Ozur...

Ali

Arkantos
23/12/2004, 01:21
Gordugun gibi, operatar+, 'const' olan bir nesne kullanmaya calismis oldu. Ya da ben seni anlamiyorum... :)

Ali

Yok ben sizi gayet iyi anladım :)

Şimdi bu operator+ işlevi:


Karmasik Karmasik::operator+ (const Karmasik & ikinci) const
{
double reelyeni, sanalyeni;
reelyeni = this->reel_ + ikinci.reel_;
sanalyeni = this->sanal_ + ikinci.sanal_;
return Karmasik (reelyeni, sanalyeni);
}


Yani işte buradaki this const Karmasik* türünden olduğu için alt kısımda sizin yaptığınız gibi const bir nesneyi eşitliğin sağına yazmak durumunda kalıyoruz. Yani operator+ işlevini const olarak bildirsek de bildirmesek de eşitliğin sol tarafı bir sabit olamaz değil mi. Yani bu sonuc değişkeni.


int main ()
{
const Karmasik sabit (1, 1);
const Karmasik degisken (1, 1);
Karmasik sonuc (0, 0);
sonuc = sabit.operator+ (degisken);
}

Ama benim bahsettiğim kısım şurasıydı:

Bende yukarıda verilen koda göre


void Karmasik::Yazdir () const
{
cout << "reel =" << reel_ << "sanal" << sanal_;
}

ve
int main ()
{
Karmasik ilk (1, 1), ikinci (2, 2), ucuncu;
ucuncu = ilk + ikinci;

}


içinde ilk, ikinci ve ucuncu birer const Karmasik olmadığı için bu

void Karmasik::Yazdir () const
{
cout << "reel =" << reel_ << "sanal" << sanal_;
}

işlevini

void Karmasik::Yazdir ()
{
cout << "reel =" << reel_ << "sanal" << sanal_;
}

şeklinde yazabiliriz diye düşünmüştüm. Çünkü bir const Karmasik nesnemiz yok.

acehreli
23/12/2004, 02:01
Tamam, simdi de ben seni cok iyi anladim. :)

Ama siniflari ve uye islevlerini yalnizca kodda kullanildiklari bir yere (ornegin ilk yere) bakarak tasarlamayiz. Siniflari, olabildigince kullanisli yapabilmek icin olabilen her islevini 'const' yapariz. const-correct kavramini basitce de boyle soyleyebiliriz: olabilen her yere const koy.

Bu durumda da Karmasik sinifi kimbilir ne durumlarda kullanilacagi icin, Yazdir islevini 'const' yapmak o sinifi daha kullanisli yapar.

Ali