C++

Başlatan muhittin_kaplan, 26 Nisan 2014, 14:57:32

z

En iyisi bir fikra anlatayim.

Amerikada ziyah beyaz ayriminin yogun olarak yapildigi yillarda bizim Temel durakda otobus bekliyormus.

Otobus gelmis millet otobuse hucum etmis ve bos bulduklari yere oturmuslar. Daha otobus hareket etmeden yok beyazlar one oturacak yok siyahlar one oturacak diye buyuk bir kavga cikmis.

Temel bakmis is karisik ayaga kalkmis. Bir dakika demis. Her kes susmus.

Temel birakin siyahi beyazi farzedin ki hepimiz yesuluz demis. Milletin cok hosuna gitmis.

Ardindan haydi hepumuz inelum tekrar binelum ama acuk yesuller one koyu yesuller arkaya otursun demis.

(ASM)
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Mr.Java

Daha önce kullanan var mı diye tavsiye istedik klişe google search yap dedin.Bak arkadaşta derleyici tavsiyesi istemiş !

Madem ki seviyemi belirlediniz bana ağır gelecekmiş.Fikirlerinizi belirtin açık forum burası.Ben anlamam başkası anlar değil mi ?

Benim için önemli olan benim doğru bildiğimdeki varsa yanlışları bana izah edecek birisi.Aksi boy gösterisi.

Konuda yeterince saptı zaten.

muhittin_kaplan

#47
siz devam edin.

mesaj birleştirme:: 28 Nisan 2014, 01:09:20

Alıntı yapılan: mufitsozen - 28 Nisan 2014, 00:29:39
Haklisiniz sayin @muhittin_kaplan. Konudan cok saptik.

Size yardimci olabilecegimiz bir bahis varsa ordan devam etmeye calisalim.
Hocam Büyük Adamsınız Vesselam. (Yanlış Anlaşılmasın, bunu Kalbimden Samimi Olarak Yazıyorum. Hala -YAPMAYAĞ MI- diyenler var.)

muhittin_kaplan


picusta

Muhittin hocam,
Forum formati icabi böyle parazitik olaylar oluyor tabii.
Pedagojik yaklasmak istiyorsun, hem kendin isin dogrusunu net olarak anlamak istiyorsun hem de yeni baslayanlar istifade etsin istiyorsun.
Gel gör ki istenmeden de olsa isine çomak sokuluyor.

Tesadüfen, uzun bir aradan sonra C++ ile bugün tekrar kod yazma sansim oldu.
Öglen basladigim projeyi aksami bitirdim. gcc ve Atmel (AVR ) kullandim (Arduino tabanli).

Projede 5 adet sinif yazdim, kisaca söyle :
- Communication :  Usb, seri ve Ethernet'ten bilgi aliyor, aldigi biligleri parser class'a gönderiyor. (Parser class'a pointer'i var), Parser class verileri  degerlendirip, kaydediyor icabinda ayni kanal'dan (Usb,seri veya ethernet, hangisinden geldi ise) cevap yaziyor

- Parser : Gelen verileri degerlendiyor: protokole göre, tabii ki state machine ile yapiliyor.  Mesaj tamamlaninca LedManager'ine haber veriyor.

- LedManager : Asil veri tabani  : Linked list seklinde Led nesnelerini tutuyor. Listeye ekleme,çikarma, arama vs.. yapiyor.

- Led : Dmx tarzi ledlerin yasam süresini, frekansini rengini vs.. ayarliyor ve hayatta tutuyor. (state machine, ve private degerler)

- LedProtokol: Led protokolü burada isleniyor, 800KHz clock'lu sinyal  üretiyor, gönderme buffer'i var.

Ana döngüde Communication sinifinin ana metodunu çagriyorum sonrada LedManagerin iki metodunu.
Her döngüde dinamik olarak birkaç LedProtokol nesnesini new ile üretip (degisik parametreler ile) sonunda delete ile yok ediyorum.

Optimizasyon olsun diye dinamik olarak ayirdigim buffer'i her nesne üretiminde static bir buffer'de tanittim. buffer'i memset yapiyorum sadece.

Tagli

Alıntı yapılan: picusta - 29 Nisan 2014, 01:35:50
- Parser : Gelen verileri degerlendiyor: protokole göre, tabii ki state machine ile yapiliyor.  Mesaj tamamlaninca LedManager'ine haber veriyor.
Aklıma geldi de, acaba bu iş için flex ve bison ikilisi kullanılabilir mi? Bu yazılımlar sonuçta lexer ve parser'ı C (veya C++) kodu olarak üretiyor. Bunu fazla zorlanmadan mikrodenetleyici içine gömebilir miyiz yoksa fazla mı ağır gelir?
Gökçe Tağlıoğlu

picusta

Alıntı Yapflex ve bison
Gerçekten agir gelir. MCU 8 bitlik , 2,5 kb RAM , 32 kb Flash'i var.RAM %80 dolu zaten, Flash ise % 60.
Burada parser dedigim aslinda gelen seri datayi state machine ile yorumlayan (baslangiç, ayiraç, son gibi ) gelen veriler ile bir nesnenin verilerini dolduran bir nesne.
Konu parser'dan açilmisken,  8 bit mikroislemci için neredeyse 0 RAM kullanan (hepsi Flash'ta) online JSON parser yazdim, günün birinde github'a open source koyarim, piyasadaki alternatiflerinden çok daha enteresan kanimca.

DNS yüzünden siteye giremedim bir süre, konuyu devam ettirmek adina söyle bir soru sorucagim :
A sinifi B sinifini kullansin diyelim. Ayni zamanda B sinifi A sinifina pointer'i var.

B nesnesi ise, kendi içisleri için C nesnesini kullaniyor. Hatta private bir fonksyonu C sinifini kullaniyor.

1. Soru :   A ve B siniflarinin .h ve .cpp dosyalari nasil olmalidir ? (asagidaki kod derlemede hata veriyor tabii)

2. Soru :   A sinifinin C sinifindan tamamen bi haber olmasi için B'nin  private fonskyonu (C'yi kullanan) nasil tanimlanmalidir  ?

Düzeltilmesi gereken kod :
A.h içerigi :

#ifndef A
#define A

#include "B.h" // B sinifini kullanmak için gerekli

class A
{
public: 
...
private :
B *Bnesnesi;   // B Nesnesine  pointer

}
#endif


B.H içerigi :

#ifndef B
#define B

#include "A.h"  // A sinifina pointer için gerekli
#include "C.h"  // iç isleri için gerekli

class B
{
public: 

private :
   A *ASinifi;                 // A 'ya pointer
   void fonskyonum(C *param); // Bu fonksyonu A sinifindan saklamak istiyorum

}
#endif



bocek

#52
şöyle yapsak:
class D; // D, A'dan daha sonra tanımlandığından burda D'nin bir class olduğu derleyiciye bildirilmeli.
class A
{
	private:
	D *Dnesnesi;
	int degisken;
};
class D // A'ya erişebilen bir sınıf tanımlıyoruz.
{
	private:
	A *Anesnesi;
};
class B : public D // A'ya erişebilmek için B'yi D'den türetiyoruz.
{
	void fonksiyonum(C *param); // B'nin kendine özel fonksiyonunu yazıyoruz.
}
// böylece A'nın C'den haberi olmuyor. hatta B'den de haberi olmuyor.
// şunları yapabiliyoruz:
B b;
C *c = new C; // burda new ile ayırdığımız belleği işimiz bitince delete ile serbest bırakmamız gerek
b.fonksiyonum(c);
b.Anesnesi = new A; // burda new ile ayırdığımız belleği işimiz bitince delete ile serbest bırakmamız gerek
b.Anesnesi->degisken = 1;
//B A'nın herşeyine erişebiliyor ama A'nın hiçbirşeyden haberi yok.
1 ya da 0. işte 'bit'ün mesele..

Tagli

Alıntı yapılan: picusta - 06 Mayıs 2014, 01:45:16
A sinifi B sinifini kullansin diyelim. Ayni zamanda B sinifi A sinifina pointer'i var.
Zaman zaman benim de bunu yapasım geliyor. Nasıl olduğunu hatırlamıyorum ama C++'da bunu yapmanın biraz dolambaçlı bir yolu vardı diye hatırlıyorum. Ama bildiğim kadarıyla eğer bunu yapmamız gerekiyorsa programın mantıksal tasarımında bir hata var demektir.
Gökçe Tağlıoğlu

picusta

Evet, @bocek arkadasimiz 1. soruya dogru cevap vermis.
Sorunun adi "recursive inclusion" (mutiple inclusion ile karistirilmamali).
Genel çözüm ise yaptigi gibi "Forward declaration" yapmaktir. Yani B sinifinda,
#include "A.h"
yerine
class A;

ile bos bir sinifi tanimlamaktir.
A *pA  satirinda A 'nin sinif oldugunu biliyor, ama hangi sinif oldugunu daha bilmiyor.
Derleyici bir sinifa pointer kadar yer ayiriyor. Her sinifin pointer (adresi) ayni alani kapliyor, ne sinifi olursa olsun.

@Tagli, bunda tasarimda mantiksal bir hata oldugunu 100%  söyleyemeyiz. Bazi pattern'lerde baska türlü olmaz.
Ne yaptigini biliyorsan sorun yok. Yoksa bos yere nesneler arasi bagimlilik olur.

2. sorunun cevabi tam olarak tatmin edici degil. Neden 4. bir sinif yapilmali ? Baska türlü olmuyor mu ? Zaten siniflari 2 dosya'ya bölüyoruz .h interface, .cpp implementation genellikle.
Bir de interface olsun diye 4. sinif mi gerekli ?
Bu C++ nesneye yönelik programlama bili olarak bir zayifligi degil midir ?
private olan metot ve memberleri  .h  yerine baska bir .h da toplayamazmiyiz ? B_intern.h diye bir doya ile ?

bocek

- her sınıfı h ve cpp diye iki dosyaya bölmek şart değil biliyorsunuz. A B C ve D'yi tek bir h ile tanımlayabiliriz. Hatta interface ve implementation'u da bir araya toplayıp tek bir cpp veya h yapabiliriz (h dosyasında clas'ın gövdesini de tanımlıyorsak genelde hpp olur uzantı : h+cpp=hpp). Ama genelde başlık ve gövde farklı dosyalarda tanımlanır ki derleyici gereksiz kod üretmesin.

- fazladan bir sınıf oluşturmanın ne sakıncası var anlamadım. başka bir yöntem muhakkak vardır tabii onu da başkası bulsun :)

- Ayrıca b_intern.h diye ayırmak, private üyeleri başka yerde public'leri başka yerde tanımlamak diye bir şey yok.

- Zayıf olan C++ değil de bizim bilgimiz galiba.
1 ya da 0. işte 'bit'ün mesele..

picusta

er sınıfı h ve cpp diye iki dosyaya bölmek şart değil biliyorsunuz. A B C ve D'yi tek bir h ile tanımlayabiliriz. Hatta interface ve implementation'u da bir araya toplayıp tek bir cpp veya h yapabiliriz (h dosyasında clas'ın gövdesini de tanımlıyorsak genelde hpp olur uzantı : h+cpp=hpp). Ama genelde başlık ve gövde farklı dosyalarda tanımlanır ki derleyici gereksiz kod üretmesin.

Evet, hepsini tek dosyada toplayabiliriz. Nihayetinde derleyici öyle yapiyor.
Ama moduler veya nesneye yönelik programlamadan ne haber ? kod tekrar kullanimi için kötü bir durum.


- fazladan bir sınıf oluşturmanın ne sakıncası var anlamadım. başka bir yöntem muhakkak vardır tabii onu da başkası bulsun :)

C++ 'de Interface diye ayri bir yapi olmadigi için, bu 4. sinif interface yerine geçiyor soyut bir sinif olmasi tercih edilir.

- Ayrıca b_intern.h diye ayırmak, private üyeleri başka yerde public'leri başka yerde tanımlamak diye bir şey yok.

C'de moduller yazinca bu sekilde iki .h dosyasi yaziliyor, biri diger programlar tarafindan dahil ediliyor, digeri sadece .c implementation da.
O tanimlanan modülde "private" veri tiplerini, prototiplerini, degiskenlerini tanimlayabiliyoruz. Benim istedigim de o, nasil C++ 'de private kimse görmeden tanimlayabiliriz ?

istedigim .NET veya Java veya .. dilindeki gibi  partial sinif tanimlama. Yani bir class birden fazla dosyada tanimlaniyor.
Bu C++'da yapilabiliyor mu, nasil yapiliyor ? Bu konuda C++ sanki sadece forward declaration'a izin veriyor .

- Zayıf olan C++ değil de bizim bilgimiz galiba.

Kanimca C++ ile OOP yazmak için dilde noksanliklar var, encapsulation zayif, birkaç takla atarak, ilave kod yazarak bunlarin üstesinden gelinebilir tabii.
O yüzden C++'dan java, C# vs.. türetilmedi mi zaten ?
Bizim bilgimiz sInIrlI, o yüzden bu forumda tartisiyoruz, ustatlardan ve bilenlerden bilgi paylasmasini talep ediyoruz.


mufitsozen

#57
Alıntı yapılan: picusta - 07 Mayıs 2014, 14:11:53

C++ 'de Interface diye ayri bir yapi olmadigi için, bu 4. sinif interface yerine geçiyor soyut bir sinif olmasi tercih edilir.


Kanimca C++ ile OOP yazmak için dilde noksanliklar var, encapsulation zayif, birkaç takla atarak, ilave kod yazarak bunlarin üstesinden gelinebilir tabii.

O yüzden C++'dan java, C# vs.. türetilmedi mi zaten ?
Bizim bilgimiz sInIrlI, o yüzden bu forumda tartisiyoruz, ustatlardan ve bilenlerden bilgi paylasmasini talep ediyoruz.

hocam saygi'da kusur etmek istemem ama evet bilginiz sinirli o yuzden c++'dan java turetilmedimi gibi COK YANLIS ifadeler kullanmayiniz. Acik forum oldugu icin daha az bilen arkadaslar burada yazildigi icin bu onermeleri dogru zannedebilir.

once C++ de OOP icin hicbir noksanlik yoktur ama cok buyuk ve karisik bir dildir. Hakimiyeti cok zordur.

C++'da interface gibi bir yapi yapmanin bircok yolu vardir ama en basiti butun fonksiyonlari virtual olan bir base class tanimlanir (vede virtual destructor) interface icin kullanilacak diger classlar bundan derive eder.  Ek olarak java'da multiple inheritance yoktur ama c++da vardir, aslinda javada interface tipi gibi bir tanimlama olmasinin nedenide javada multiple inheritance olmamasidir. Multiple inheritance kullanimi zordur bazi kurallara uymak gerekir, biraz daha tecrubeli olmak gerekir vb.

Bunun disinda eger amac javadaki gibi implementation detaylarini saklamak ve kullanicilara sabit bir arabirim sunmaksa c++da pimpl idiomuda kullanilabilir.


sayin @muhittin_kaplan"dan ozur dilerim. onun actigi bir konu basligi oldugunu farketmeden yazmisim. Yukaridaki yazilanlari yok farzedebilirsiniz.
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

picusta

Bu konuda bilgim sInIrlI tabii, önemli olan tartismaktir ve bilenlerin yol göstermesidir diye düsünüyorum.
Alıntı YapC++'da interface gibi bir yapi yapmanin bircok yolu vardir ama en basiti butun fonksiyonlari virtual olan bir base class tanimlanir (vede virtual destructor) interface icin kullanilacak diger classlar bundan derive eder.  Ek olarak java'da multiple inheritance yoktur ama c++da vardir, aslinda javada interface tipi gibi bir tanimlama olmasinin nedenide javada multiple inheritance olmamasidir. Multiple inheritance kullanimi zordur bazi kurallara uymak gerekir, biraz daha tecrubeli olmak gerekir vb.
Evet tamamen katiliyorum, benimde bir önceki mesajimda anlatmak istedigim bu : interface olayi soyut (virtual) bir sinif ile halledilmeli.
Sorumun amaci Baska bir yöntem var mi ?  diye merak etmem.

Alıntı Yapjavada interface tipi gibi bir tanimlama olmasinin nedenide javada multiple inheritance olmamasidir.
Benim bilidigim kadari ile neden - > sonuç iliskisi tam tersi, yani Java'yi tasarlayan isteyerek multiple inheritance'i yasaklamis, bu yüzden interface diye soyut siniflari ayirmis.

Bu konu ile ilgili söyle bir soru geliyor aklima:  C++ 'da iki siniftan (A ve B) türeyen bir sinif var diyelim, C sinifi. Tesaddüf A ve B'de ayni isimli fonksyonlar var.
Bu durumda nasil C sinifi A.fonk() ve B.fonk() ' u implement ediyor ?

Benim "türetildi" kelimesi tam olmamis tabii, anlamini açmak lazim. Yakin zamanda Java'nin tarihçesini okudum, orada asagi yukari böyle bir ibare vardi. demekten amacim, aslinda Java'yi yazan C++ 'dan esinlenerek yazilmasi, syntax'i asagi yukari ayni, birçok seyi atilmis, yerine yenileri getirilmis gibi .
Demek istedigim Java dili,  BASIC, COBOL, PASCAL, ADA, FORTRAN vs.. degilde, C++ 'u temel alinarak tasarlanmis. C#'ta isim benzerliginden belli.


@gerbay:  Hocam, .h 'da private tiplerin olmasi mesela rahatsiz ediyor. B sinifini kullanan niye B'nin private degiskenlerini bilsin ki ? Saklamak için ilave seyler yazmak gerekiyor.

@mufitsozen 'nin dedigi gibi mesela:
Alıntı YapBunun disinda eger amac javadaki gibi implementation detaylarini saklamak ve kullanicilara sabit bir arabirim sunmaksa c++da pimpl idiomuda kullanilabilir.
O yüzden OOP için dil kendinden kolaylik saglamiyor (diger diller'e nazaran).
Yani ayni programi C++ veya diger OOP'ye "yatkin" bir dille yazmaya kalksak,
C++'de digerine göre daha çok "satir" kod yazmak zorunda kaliriz gibime geliyor. (sadece OOP kismi için : nesne tanimlama vs...)


picusta

Bu konu ana fikrinden daha önce saptirilmis nahos tartismaya dönüsmüstür .
Ana konu C++,  xx dili degil veya karsilastirma degil.
Benim maksadim muhittin_kaplan'nin açtigi ana konuyu tekrar ayni ruh ile canlandirmak ve olaya pedagojik olarak yaklasmak, herseyi birden ortaya dökmeden adim adim gitmek.

C++'da nasil yapilir sorularini sormak, baska yolu varmi, bilgilenmek devami gelir diye bir iki kavrama deginmek : inheritance, inclusion, pimpl ve forward declaration idiom larini da görmüs olduk.

Yaptigim hata bir soruda C++'da bu nasil yapilir diye sorarken  xxx ve C# dilinden örnek vermem oldu, buda yanlis anlasilip parazitik tartisma hortlatti.
Üzüm yemek mi, bagciyi dövmekmi ?

Simdi konuya dönelim ve kalan sorulara bakalim :
Alıntı YapBu konu ile ilgili söyle bir soru geliyor aklima:  C++ 'da iki siniftan (A ve B) türeyen bir sinif var diyelim, C sinifi. Tesaddüf A ve B'de ayni isimli fonksyonlar var.
Bu durumda nasil C sinifi A.fonk() ve B.fonk() ' u implement ediyor ?

Evet güzel bir noktaya deginmissiniz, Arduino'nun yayilmasina C++ büyük katki sagladi, bu sayede derli toplu ve kolay kullanilan kütühaneler olustu.

Kendi fikrimce Z hocanin yaptigi ZIOS'u da C++ ile olsaydi, çok daha kullanisli olurdu.