Tam Sürümünü Görmek İçin : STL Container'ları ile Polymorphism kullanımı
Darkstar
20/12/2004, 19:58
STL Container'ları ile Polymorphism uygulamasını anlatan çok faydalı örnek bir kod parçası, işinize yarayacağını zannediyorum:
//: C20:Stlshape.cpp
// Simple shapes w/ STL
#include <vector>
#include <iostream>
using namespace std;
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() {};
};
class Circle : public Shape {
public:
void draw() { cout << "Circle::draw\n"; }
~Circle() { cout << "~Circle\n"; }
};
class Triangle : public Shape {
public:
void draw() { cout << "Triangle::draw\n"; }
~Triangle() { cout << "~Triangle\n"; }
};
class Square : public Shape {
public:
void draw() { cout << "Square::draw\n"; }
~Square() { cout << "~Square\n"; }
};
typedef std::vector<Shape*> Container;
typedef Container::iterator Iter;
int main()
{
Container shapes;
shapes.push_back(new Circle);
shapes.push_back(new Square);
shapes.push_back(new Triangle);
for(Iter i = shapes.begin();
i != shapes.end(); i++)
(*i)->draw();
// ... Sometime later:
for(Iter i = shapes.begin();
i != shapes.end(); i++)
delete *i;
} ///:~
acehreli
21/12/2004, 01:59
Bunu daha once de konustugumuzu hatirliyorum... :) Oyle "Sometime later" diyip oyle nesneleri teker teker silemezsin babam! :) Bu yontem ancak boyle kucuk bir programda isler.
Daha karmasik bir programda "Sometime later" ile belirtilen yerden atilabilecek olan bir hata, delete satirlarinin isletilmemesi ve bellek kaybedilmesine neden olur.
Yine, tek kullanisli yontem, akilli gostergeler kullanmaktir. Ornegin ise Container'i soyle tanimlayarak baslamamiz gerekir:
#include <boost/shared_ptr.hpp>
/* ... */
typedef boost::shared_ptr<Shape> ShapePtr;
typedef std::vector<ShapePtr> Container;
// Ondan sonra:
shapes.push_back(ShapePtr(new Circle));
Ek olarak delete *i; yapan dongu de ortadan kalkar...
Eger yanilmiyorsam butun degisiklikler bu kadardir: guvensiz programdan guvenli programa gecmis oluruz. :)
Ali
Darkstar
21/12/2004, 18:51
Walla bu kodu yazan Bruce Eckel, Thinking in C++ kitabında vermiş bu örneği. Artık bu yorumu bi zahmet kendisine maillersin :)
Bu arada "boost" kütüphanesi beleşmidir? yoksa reklam mı yapıyorsun hocam? Bilelim yani :)
Bir de delete satırlarından atılabilecek bir exception'da bellek kaybı olur demişsin. İyi de delete sonrası bir exception atılırsa %99.9 bir hata mesajı verilir program exit edilir benim bildiğim.. Ve program terminate ederse zaten almış oldugum tüm belleği otomatik olarak sisteme geri verir. Yanlış mı?
Arkantos
21/12/2004, 19:12
Bu arada "boost" kütüphanesi beleşmidir? yoksa reklam mı yapıyorsun hocam? Bilelim yani :)
Boost kütüphanesi ücretsizdir. Boost kütüphanesi C++ Standartlaştırma Komitesi Grubu üyeleri tarafından yazılmaya başlanmış olup şu anda C++ topluluğundaki binlerce C++ programcısı Boost'un gelişimine katkıda bulunmaktadır. 10 tane Boost kitaplığı C++'nin gelecekteki standartlarına ve dolayısıyla C++'ye eklenecektir. Bilgilerinize sunulur..
http://www.boost.org/
Volkan Uzun
21/12/2004, 19:12
belestir :) bende yeni ogreniyorum, download et kullan fena degil biraz anlamasi ilk basta karisik olsada :)
acehreli
21/12/2004, 19:19
Darkstar, Thinking in C++ bayagi eski bir kitaptir. Bruce Eckel'in soylediklerime bugun karsi cikacagini sanmam. :)
Hata atildiginda tehlike olusacak olan yer, "sometime later"dan onceki yer aslinda. Yanlis soylemisim... Aslinda "sometime later" sozunden once bir "..." var ya; iste orada isletildigi varsayilan koddan bir hata atilirsa delete satirlarina erisemeyiz.
Ali
Darkstar
22/12/2004, 00:25
yani neticede delete exception'undan sonra program terminate eder... Problem yok!
acehreli
22/12/2004, 02:29
Ben de bu programda sorun olmadigini biliyorum. Onun icin de "bu yontem ancak boyle kucuk bir programda isler" demistim. Ozel olarak bu program hakkinda konusmuyorum. Genel olarak, delete'in kod icine acikca yazilmis olmasi durumu uzerine konusuyorum.
Ayrica, tam olarak anlasabildigimizden de emin degilim... Daha once "delete satirlarindan atilabilecek bir exception" dedin. Simdi de "delete exception"i... Bu soylediklerinin ikisi de anlamli degil. Cunku atilan hatanin delete ile hic bir ilgisi yok.
Hata atilmis olabilecegi icin biz delete satirlarina gelemiyor olabiliyoruz.:)
Bu konuda artik anlasmis olmamiz gerektigini dusunuyorum, cunku simdi verecegim ornegi daha once bu forumda cok sayida yazdim. Anlasilabilir olmasi icin ozellikle basit bir hale indirgiyorum:
void bar();
void foo()
{
Sekil * sekil = new Ucgen;
bar(); // ve baska islemler
delete sekil;
}
Yukaridaki islevdeki hatali kullanimi goruyor musun? Eger acik degilse, bar'in soyle tanimlandigini dusun:
void bar()
{
throw 0;
}
Yani, 'delete sekil;' ifadesi hicbir zaman isletilemiyor! Goruyor musun? Bu yanlisligin ortadan kalkmasi icin de en iyi yol, akilli gostergeler kullanmaktir. foo soyle yazilmalidir:
typedef AkilliGosterge<Sekil> SekilPtr;
void foo()
{
SekirPtr sekil(new Ucgen);
bar();
}
[Not: Dikkat edersen, boost::shared_ptr kullanmadim. Onun yerine, bellegi geri vermeyi bilen herhangi baska bir akilli gosterge kullanabilirsin. boost::shared_ptr cogunlukca benimsendigi icin ben de onu yegliyorum.]
Bruce Eckel'in programini bir kenara birakalim; cunku ben Bruce Eckel'in bile o programdaki kullanimi bu nedenden oturu kotu bulacagindan emin gibiyim. Tek savunmasi, senin de dedigin gib programin cok basit oldugudur. Veya, kitabi okuyanlari gereksiz ayrintilarla ugrastirmamak icin olabilir. (Aslinda Bruce Eckel artik pek C++ da takilmiyor.)
Bence once yukaridaki hatayi konusalim... Sen onun hatali bir kod olduguna katiliyor musun? Oyleyse anlasiyoruz...
Ali
Darkstar
22/12/2004, 20:06
Ok no problem o zaman.
Akıllı pointerlar iyi hoş da kullanımı biraz çirkin gibi.. Basitce
Sekil* ptr = new Sekil();
demek yerine SekirPtr sekil(new Ucgen); demek biraz tuhaf geliyor, belki alışmadıgımızdandır bilemiyorum. Bir de akıllı gösterge kullandığımızda garbage collector kullanabiliyormuyuz bunu da incelemek lazım. Aslında kaliteli bir GC bulunursa akıllı gösterge veya delete v.s. ile ugrasmak zorunda kalmadan direk silme işlemini GC'ye bırakmak çok mantıklı..
Arkantos
22/12/2004, 20:16
Garbage Collection C++.NET'de yani Managed C++ 'de var. Böyle nesnelerin ömürleriyle uğraşmak falan pek sarmıyo falan diyorsan Managed C++ öğrenmeni tavsiye ederim :)
Darkstar
22/12/2004, 23:20
ehehe sarmıyo tabi ama solaris'te olunca elin mahkum :)
acehreli
23/12/2004, 00:22
Haklisiniz, C++ ancak "managed" ortamlarda var.
Ben "garbage collection"i tartismasina girecek kadar bilmiyorum, ama hem lehine hem de aleyhine cok sayida gorus okdum. Anladigim kadariyla; rahatca kullanilabilecegi uygulamalar oldugu kadar, temizligin ona birakilmasinin dogru olmadigi uygulamalar da var.
Programcinin duruma gore gerekeni yapmasi gerekiyor.
Ben su ana kadar akilli gostergelerle *hic* bellek kaybi yasamadan yaziyorum. Ama dogrusu, bir arkadasimin "circular reference" (iki nesnenin birbirini gosterme durumu) durumlarinda ne yaptigim sorusunu da yanitlayamamistim. Henuz hic oyle durumlara dusmedigim icin olsa gerek... :)
Ali
Forum Yazılımı : vBulletin v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.