Yazan: Yrd. Doç. Dr. Şadi Evren ŞEKER

Bu yazının amacı, C bilen kişiler için C++ diline hızlı bir başlangıç yapmaktır. Bu yazıda, C++ dilinin, temel özelliklerinden bahsedilecektir. Yazıda eğitim amaçlı olarak hazırlanan bir kod üzerinden temel C++ kavramları açıklanırken, C++ dilinin, nesne yönelimli programlama özellikleri, farklı bir yazıda ele alınmıştır. Lütfen bu yazı için “C++ ve Nesne Yönelimli Programlama” başlıklı yazıyı okuyunuz.

C++ dili, C dilinin desteklediği bütün özellikleri destekleme iddiasını taşır. Bu yüzde C dilinde bilinen bütün özellikler destekleneceği gibi bazı farklılıklar içerir.

Biz klasik olarak yazılan “Merhaba Dünya” (Hello World) uygulaması ile işe başlayalım.

#include <iostream>
   int main(){
   std::cout  << "merhaba dünya" << std::endl;
   return 0;
}

Yukarıdaki kodda görüldüğü üzere klasik stdio.h kütüphanesi yerine iostream kullanılmıştır. C++ dilinin ana kütüphanesidir. Ayrıca alıştığımız main fonksiyonu C++ dilinde de bulunmaktadır.

Printf fonksiyonu yerine cout kullanılır. Burada dikkat edilecek bir husus, cout fonksiyonunun std isim uzayında (namespace) olmasıdır. Bu isim uzayını sürekli tekrarlamak yerine C++ dilinde bulunan

using namespace std;

satırı yazılabilir. Kodumuz yeni haliyle aşağıdaki şekildedir:

#include <iostream>
using namespace std;
int main(){
   cout  << "merhaba dünya" << endl;
   return 0;
}

Yukarıdaki yeni kodda, cout ve endl başından std kaldırılmış yerine yeni bir satır olarak using namespace std eklenmiştir. Bu eklemenin anlamı, bir fonksiyon veya değerin başına hiçbir şey yazılmazsa bu fonksiyon veya değerin std isim uzayından olduğudur.

Bunun dışında C dilinde olan özelliklerin tamamı C++ dilinde kullanılabilir.

Örneğin aşağıdaki basit kodu ele alalım:

#include <iostream>
using namespace std;
int main(){
   int b;
   b= 10;
   int a = 10;
   int c = 30, d = 40;
   cout << a << endl;
   cout <<"a +  b = " << a+b << endl;
   c = a * b + d;
   cout << c << endl;
}
Yukarıdaki kodun ekran çıktısı aşağıdaki şekildedir:

Örnek olarak C++ dilinin daha fazla özelliğinin kullanıldığı bir kodu ele alalım. Aşağıda, klasik bir uygulama olarak çok terimli (polynom) üzerinde işlem yapmaya yarayan bir kod Mark Allen Weiss’in kitabından Türkçelenmiş ve ufak düzenlemelere tabi tutulmşutur:

#include <iostream>
#include <conio.h>
#include <ostream>
using namespace std;
class CokTerimli{
enum { Azm_US = 100 };
friend int main( );
public:
   CokTerimli( );
   void sifirCokTerimli( );
   CokTerimli operator+( const CokTerimli & st ) const;
   CokTerimli operator*( const CokTerimli & st ) const;
   void goster( ostream & out ) const;
private:
   int katSayilar[Azm_US];
   int usDerecesi;
};
int max( int a, int b ){
   return a > b ? a : b;
}
CokTerimli::CokTerimli( ){
   sifirCokTerimli( );
}
void CokTerimli::sifirCokTerimli( ){
   for( int i = 0; i <= Azm_US; i++ )
      katSayilar[ i ] = 0;
   usDerecesi = 0;
}
CokTerimli CokTerimli::operator+( const CokTerimli & st ) const{
   CokTerimli sum;sum.usDerecesi = max( usDerecesi, st.usDerecesi );
   for( int i = sum.usDerecesi; i >= 0; i-- )
      sum.katSayilar[ i ] = katSayilar[ i ] + st.katSayilar[ i ];
   return sum;
}
CokTerimli CokTerimli::operator*( const CokTerimli & st ) const{
   CokTerimli product;
   product.usDerecesi = usDerecesi + st.usDerecesi;
   if( product.usDerecesi > Azm_US )
      cerr << "operator* , Azm_US derecesini geciyor" << endl;
   for( int i = 0; i <= usDerecesi; i++ )
      for( int j = 0; j <= st.usDerecesi; j++ )
         product.katSayilar[ i + j ] +=katSayilar[ i ] * st.katSayilar[ j ];
   return product;
}
ostream & operator<<( ostream & sonuc, const CokTerimli & st ){
   st.goster( sonuc );
   return sonuc;
}
void CokTerimli::goster( ostream & out ) const{
   for( int i = usDerecesi; i > 0; i-- )
      out << katSayilar[ i ] << "x^" << i << " + ";
   out << katSayilar[ 0 ] << endl;
}
int main( ){
   CokTerimli p;
   CokTerimli q;
   p.usDerecesi = 1;
   p.katSayilar[ 0 ] = 1;
   p.katSayilar[ 1 ] = 1;
   q = p + p;
   p = q * q;
   cout << q << endl;
   getch();
   return 0;
}

Yukarıdaki kodun çıktısı aşağıdaki şekildedir:

Şimdi bu kodu anlamaya çalışalım ve kod üzerinden bazı C++ kavramlarını tanıyalım.

İlk olarak çok terimlilerin tanımlandığı sınıf(class) tanımına bakmakta yarar var. Kodun bu kısmı aşağıda alıntılanmıştır.

class CokTerimli{
enum { Azm_US = 100 };
friend int main( );
public:
   CokTerimli( );
   void sifirCokTerimli( );
   CokTerimli operator+( const CokTerimli & st ) const;
   CokTerimli operator*( const CokTerimli & st ) const;
   void goster( ostream & out ) const;
private:
   int katSayilar[Azm_US];
   int usDerecesi;
};

Kodun bu kısmında, CokTerimli isimli bir sınıf tanımlanmıştır. Bu tanıma göre Azm_US isminde bir değişken enumurator (sayma, tâdâd) olarak tanımlıdır. Bu değişkenin tanımındaki amaç, kodun ilerleyen kısımlarında en fazla 100 terimli bir polinoma izin verilmesi ve kodda bu şekilde bir sınır konulmasıdır. Kısaca en yüksek polinom derecemizi 100 olarak tanımlamış ve bu sayede dizi tanımları gibi bazı tanımları kolaylaştırmış oluyoruz.

Bilindiği üzere, main fonksiyonu, özel bir fonksiyondur ve C++ dilinde öncelikli olarak çalıştırılır. Bu fonksiyonu friend olarak tanımlayarak, bu fonksiyonun içerisinden, CokTerimli sınıfındaki değerlere doğrudan erişilme izni verilmiş olunur. Sınıfımızda, private tipinde tanımlı olan katsayılar dizisi (array) ve usDerecesi değişkeni, normalde dışarıdan erişime kapalıdır. Private olarak tanımlanan erişim belirleyicisi (Access modifier), dışarıdan erişimlere izin vermez. Ancak main fonksiyonunu friend olarak tanımlayarak bu erişime izin veriyoruz.

Ardından kodumuzdaki pbulic alanda tanımlı olan CokTerimli isimli fonksiyon, özel bir fonksiyondur. Bu fonksiyon dikkat edileceği üzere sınıf (class) ile aynı isme sahip ve dönüş değeri olmayan bir fonksiyondur. Bu fonksiyona yapıcı (constructor) ismi verilir. Bu fonksiyonun özelliği, bu sınıftan bir nesne (object) oluşturulduğunda, ilk çalışan fonksiyon olmasıdır.

Ayrıca public alanda iki adet operatör ile başlayan tanım yapıldığını görüyoruz. Bu tanımlar operatör üzerine yükleme (operator overloading ) olarak geçer ve normalde + ve * işlemlerinin mevcut tanımlarını değiştirmeye yönelik kodlardır. Bilindiği üzere + işlemi toplama ve * işlemi ise çarpma anlamındadır. Oysa biz bu işlemleri, çok terimliler için yeniden programlıyoruz ve artık iki çok terimliyi toplamak veya çarpmak için kullanmak istiyoruz.

Bu tanımlanan fonksiyonların kodlaması ile devam edelim:

CokTerimli::CokTerimli( ){
   sifirCokTerimli( );
}
void CokTerimli::sifirCokTerimli( ){
   for( int i = 0; i <= Azm_US; i++ )
      katSayilar[ i ] = 0;
   usDerecesi = 0;
}

Görüldüğü üzere ilk fonksiyon bir yapıcıdır (constructor) ve sifiCokTerimli fonksiyonunu çağırmıştır. Çağrılan bu fonksiyonda ise, bir döngü ile katsayıların tutulduğu dizi sıfırlanmış ve usDerecesi 0 olarak atanmıştır. Kısaca polinom ilklenmiştir (initialise). Ardından gelen 3 fonksiyon ise işlem üzerine yüklemedir (operator overlaoding)

CokTerimli CokTerimli::operator+( const CokTerimli & st ) const{
   CokTerimli sum;sum.usDerecesi = max( usDerecesi, st.usDerecesi );
   for( int i = sum.usDerecesi; i >= 0; i-- )
      sum.katSayilar[ i ] = katSayilar[ i ] + st.katSayilar[ i ];
   return sum;
}
CokTerimli CokTerimli::operator*( const CokTerimli & st ) const{
   CokTerimli product;
   product.usDerecesi = usDerecesi + st.usDerecesi;
   if( product.usDerecesi > Azm_US )
      cerr << "operator* , Azm_US derecesini geciyor" << endl;
   for( int i = 0; i <= usDerecesi; i++ )
      for( int j = 0; j <= st.usDerecesi; j++ )
         product.katSayilar[ i + j ] +=katSayilar[ i ] * st.katSayilar[ j ];
   return product;
}
ostream & operator<<( ostream & sonuc, const CokTerimli & st ){
   st.goster( sonuc );
   return sonuc;
}

C++ dilinde, işlem üzerine yükleme için, işlemin sonuç tipi operantların tipleri ve işlem bilgileri verilmelidir. Örneğin toplama işlemini ele alalım:

a + b

Bu işlemde + operatörünün iki operandı vardır (a ve b) ve işlem sonuç olarak bir değer döndürür. Örneğin bu işlem sayılar arasındaki toplama işlemi ise sonuç bir sayı olacaktır

4 + 7

İşleminin sonucunun bir integer olması gibi .

Yukarıdaki işlem üzerine yüklemelerde de yapılan aynen bu işlemin yeniden tanımlanmasıdır. Kodumuzdaki amaç çok terimliler için bir sınıf kodlamaktı. Bu sınıfta, birden fazla çok terimliyi toplamak, çarpmak veya yönlendirmek (redirect, << işlemi ) yapılmaktadır. Örneğin toplama işlemini ele alalım.

P= X2 + 3x + 7

Q= 4x3 + 2x2 + x + 9

Yukarıdaki bu iki polinomun toplamı, aslında katsayılar dizilerinin toplamıdır. Bu toplama işlemi için iki polinomun katsayıları, denk düşen üsler için toplanır.

Bizim örneğimizde, programcı, R = P + Q şeklinde bir işlem çağırdığı zaman, sonuçta dönecek değer bir polinom olacaktır, dolayısıyla opeartör üzerine yüklemenin dönüş tipi bir polinomdur. Kodun içerisinde ise iki polinomdan yüksek üste sahip olanı bulunup bu üst derecesine kadar dönen bir döngü marifetiyle, katsayılar toplanmaktadır.

Son olarak, kodumuzun ana fonksiyonunu inceleyerek örneğimizi anlamaya çalışalım.

int main( ){
   CokTerimli p;
   CokTerimli q;
   p.usDerecesi = 1;
   p.katSayilar[ 0 ] = 1;
   p.katSayilar[ 1 ] = 1;
   q = p + p;
   p = q * q;
   cout << q << endl;
   getch();
   return 0;
}

Bu örnekte, p ve q isimli iki polinom tanımlanmış ve p polinomuna, x + 1 değeri konulmuştur. Bu atama işlemi, p polinomunun üstünü 1 yapıp 0. Ve 1. Katsayılara 1 değerini koyduğumuz satırda görülebilir.

Ardından q polinomu, p polinomunun kendisi ile toplamından elde dilmiş : 2x + 2 değerine atanır.

Son olarak , p = q * q işlemi ile, sonuç değerine ulaşılmıştır. Kodun, main fonksiyonu içerisinde görüldüğü üzere sınıf tanımı içerisinde yazılan operatör üzerine yüklemelerinden faydalanılmıştır.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir