# C++ ile Nesne Yönelimli Programlama

> C++ sınıfları, nesne ömrü, referanslar, kaynak yönetimi, aşırı yükleme, kalıtım, çok biçimlilik, akışlar ve standart kütüphane üzerine ayrıntılı ders notları.

- Author: Muhammet Ali Köker
- Language: tr
- Canonical: https://alikoker.com.tr/cpp-ile-nesne-yonelimli-programlama
- Translation: https://alikoker.com.tr/en/object-oriented-programming-with-cpp
- Published: 2014-10-12T19:05:00+03:00
- Modified: 2026-07-14T18:25:00+03:00
- Verified: 2026-08-08T15:00:00+03:00
- Type: article

C++ notları, aynı dönem tuttuğum C/C++ ders notlarının nesne yönelimli programlama ve kaynak yönetimi tarafını oluşturuyordu. Sonraki yıllarda C++11 sonrasında yerleşen bazı kavramları ekledim; ancak sınıf, nesne ömrü, kalıtım, çok biçimlilik ve standart kütüphane eksenindeki ilk ders yapısını korudum.

## Ünite 1: C++'a Geçiş

### C ve C++ ilişkisi

C++ birçok C sözdizimi öğesini paylaşır ancak iki dil birebir uyumlu değildir.

Geçerli C kodu her zaman geçerli C++ değildir.

Örnek farklar:

- tür dönüşümü kuralları,
- `void *` dönüşümleri,
- karakter sabitlerinin türü,
- anahtar sözcükler,
- designated initialization ayrıntıları,
- değişken uzunluklu diziler,
- standart kütüphane kullanımı.

Bu nedenle `.c` dosyasını yalnız `.cpp` olarak yeniden adlandırmak sistematik bir C++ geçiş yöntemi değildir.

### C++ programının temel yapısı

```cpp
#include <iostream>

int main()
{
    std::cout << "Merhaba\n";
}
```

C++'ta `main` dönüş türü yine `int`tir.

`return 0;` satırı `main` sonunda yazılmasa da başarılı sonlandırma kabul edilir, ancak açık yazımı öğretici olabilir.

### namespace

Standart C++ kütüphanesinin isimleri:

```cpp
std::
```

ad alanındadır.

Örnek:

```cpp
std::cout
std::string
std::vector
```

Genel başlık dosyalarında:

```cpp
using namespace std;
```

kullanmak ad çakışmalarını büyütebildiği için önerilmez.

### C++ başlatma biçimleri

```cpp
int a = 10;
int b(10);
int c{10};
```

C++ farklı initialization biçimlerine sahiptir.

Süslü parantezli initialization daraltıcı dönüşümleri engelleyebilir:

```cpp
int x{3.14};   // hata
```

Bu nedenle modern C++ kodunda `{}` sık kullanılır.

### auto

```cpp
auto count = 10;
auto ratio = 2.5;
```

`auto` derleyicinin türü initializer'dan çıkarmasını sağlar.

Türü gizlemek amacıyla değil, açıkça çıkarılabildiği veya karmaşık türün tekrarının gereksiz olduğu yerlerde kullanılması uygundur.

### const ve constexpr

`const` nesnenin ilgili erişim yoluyla değiştirilememesini sağlar.

```cpp
const int limit = 100;
```

`constexpr` ise sabit ifade bağlamında kullanılabilen değer veya işlevleri tanımlamak için kullanılır:

```cpp
constexpr int square(int x)
{
    return x * x;
}
```

### nullptr

C++11 ve sonrasında null pointer için:

```cpp
nullptr
```

tercih edilir.

```cpp
int *p = nullptr;
```

`0` veya `NULL` kullanımındaki bazı overload belirsizliklerini ortadan kaldırır.

### Giriş ve çıkış

```cpp
int value{};
std::cin >> value;
std::cout << value << '\n';
```

Metin satırı:

```cpp
std::string line;
std::getline(std::cin, line);
```

ile okunabilir.

### std::string

C++'ta metin için standart sınıf:

```cpp
std::string
```

kullanılır.

```cpp
std::string first = "Ali";
std::string last = "Koker";
std::string full = first + " " + last;
```

C karakter dizileri gerektiğinde kullanılabilir, ancak genel uygulama kodunda `std::string` bellek yönetimini ve birçok işlemi daha güvenli hale getirir.

### std::vector

Dinamik dizi için:

```cpp
std::vector<int> values;
```

kullanılabilir.

```cpp
values.push_back(10);
values.push_back(20);
```

Bellek yönetimini otomatik yapar.

Ham:

```cpp
new int[n]
```

yerine sahiplik gereksinimi yalnız dinamik dizi ise çoğunlukla `std::vector` daha uygundur.

## Ünite 2: Nesneye Yönelik Programlama

### Nesne ve sınıf

Sınıf:

- veri,
- bu veri üzerinde çalışan işlevler,
- erişim kuralları,
- nesne yaşam döngüsü

için bir tür tanımıdır.

Örnek:

```cpp
class Counter {
public:
    void increment()
    {
        ++value_;
    }

    int value() const
    {
        return value_;
    }

private:
    int value_{};
};
```

Nesne:

```cpp
Counter c;
```

sınıfın örneğidir.

### Soyutlama

Soyutlama, kullanıcının gerekli davranışı görmesini, gereksiz gerçekleştirim ayrıntılarından bağımsız kalmasını sağlar.

Örneğin:

```cpp
account.withdraw(100);
```

çağrısının kullanıcı tarafı:

- bakiyenin hangi veri yapısında tutulduğunu,
- işlem kaydının nasıl saklandığını,
- doğrulamanın nasıl yapıldığını

bilmek zorunda değildir.

İyi soyutlama "hangi iş yapılabilir?" sorusunu açık, "nasıl yapılıyor?" ayrıntısını ise gerektiği kadar gizli tutar.

### Kapsülleme

Kapsülleme yalnız alanları `private` yapmak değildir.

Asıl amaç:

- sınıfın geçerli durum koşullarını korumak,
- dış kullanımı kontrollü arabirim üzerinden yapmak,
- iç gerçekleştirimi değiştirebilmektir.

Örnek:

```cpp
class BankAccount {
public:
    explicit BankAccount(double initial)
        : balance_{initial}
    {
    }

    bool withdraw(double amount)
    {
        if (amount < 0 || amount > balance_) {
            return false;
        }

        balance_ -= amount;
        return true;
    }

    double balance() const
    {
        return balance_;
    }

private:
    double balance_{};
};
```

Dış kod:

```cpp
account.balance_ = -1000000;
```

gibi sınıfın kuralını bozan doğrudan değişiklik yapamaz.

### public, private ve protected

`public` üyeler sınıfın dış arabirimidir.

`private` üyeler sınıf dışından doğrudan kullanılamaz.

`protected` üyeler sınıf ve türetilmiş sınıflardan erişilebilir.

Veri alanlarını varsayılan olarak `private` tutmak, davranışı üye işlevlerle yönetmek yaygın tasarım ilkesidir.

### struct ve class

C++'ta `struct` ile `class` yetenek bakımından büyük ölçüde aynıdır.

Temel fark varsayılan erişimdir:

```text
struct -> public
class  -> private
```

Ayrıca `struct` için varsayılan kalıtım `public`, `class` için `private`dır.

Basit veri taşıyan türlerde `struct`, invariant ve davranış içeren kapsüllenmiş türlerde `class` kullanımı yaygın bir gelenektir.

### Kurucu

Constructor nesnenin başlangıç durumunu kurar.

```cpp
class Point {
public:
    Point(int x, int y)
        : x_{x}, y_{y}
    {
    }

private:
    int x_;
    int y_;
};
```

Üye initializer list:

```cpp
: x_{x}, y_{y}
```

üyelerin gövdeden önce doğrudan başlatılmasını sağlar.

### Varsayılan kurucu

```cpp
class Point {
public:
    Point() = default;
};
```

derleyici tarafından üretilebilen davranışı açıkça talep eder.

### explicit

Tek argümanlı kurucularda istenmeyen örtük dönüşümleri engellemek için:

```cpp
explicit Distance(double meters);
```

kullanılabilir.

### Yıkıcı

Destructor:

```cpp
~Resource()
{
    ...
}
```

nesnenin yaşamı bittiğinde çalışır.

Modern C++'ta destructor'ın temel önemi RAII ile kaynak serbest bırakmadır.

### RAII

Resource Acquisition Is Initialization, kaynağın nesne yaşam süresine bağlanmasıdır.

Örnek kaynaklar:

- dinamik bellek,
- dosya,
- mutex,
- socket,
- işletim sistemi handle'ı.

```cpp
{
    std::ifstream input{"data.txt"};
    // ...
}
```

blok sonunda `input` nesnesinin destructor'ı dosyayı kapatır.

Bu yaklaşım exception dahil bütün çıkış yollarında kaynak yönetimini güvenilir hale getirir.

### Bir nesneyi diğerine atama

```cpp
Point a{1, 2};
Point b{3, 4};

b = a;
```

sınıfın copy assignment işlemini çağırır.

Kullanıcı özel bir kopyalama semantiği tanımlamazsa uygun koşullarda derleyici üye bazlı kopyalama üretir.

### Kopya kurucusu

```cpp
Type(const Type& other);
```

mevcut nesneden yeni nesne oluşturur.

### Taşıma semantiği

Modern C++'ta kaynak sahipliğini kopyalamadan aktarabilmek için move semantics bulunur.

```cpp
Type(Type&& other);
Type& operator=(Type&& other);
```

Bu özellikle:

- dinamik kaynak sahipliği,
- büyük container'lar,
- geçici nesneler

için önemlidir.

### Rule of Zero

Sınıf kaynak yönetimini doğrudan ham işaretçilerle yapmak yerine:

- `std::vector`,
- `std::string`,
- `std::unique_ptr`,
- standart kaynak yöneticileri

kullanıyorsa çoğu durumda destructor, copy ve move işlevlerini elle yazmaya gerek kalmaz.

Bu **Rule of Zero** yaklaşımıdır ve modern C++ için tercih edilir.

## Ünite 3: C++ Referansları, Nesne İşaretçileri ve Bellek Yönetimi

### Referans

C++ reference:

```cpp
int x = 10;
int& ref = x;
```

başlangıçta bir nesneye bağlanır.

```cpp
ref = 20;
```

`x` değerini değiştirir.

C++ referansı C'deki işaretçi ile aynı dil özelliği değildir.

### Değer ile parametre

```cpp
void f(int x);
```

nesnenin değeri fonksiyon parametresine aktarılır.

### const referans

Büyük nesneleri kopyalamadan salt okunur geçirmek için:

```cpp
void print(const std::string& text);
```

kullanılabilir.

### Referans ile değiştirme

```cpp
void increment(int& value)
{
    ++value;
}
```

çağıranın nesnesini doğrudan değiştirebilir.

### İşaretçi ve referans seçimi

Kabaca:

- null olabilme anlamlıysa işaretçi,
- "bu nesne mutlaka vardır" ilişkisi varsa referans

uygun olabilir.

Ancak sahiplik, yaşam süresi ve API sözleşmesi de seçime dahildir.

### this

Statik olmayan üye işlev içinde:

```cpp
this
```

mevcut nesneyi gösterir.

```cpp
class Point {
public:
    Point& setX(int x)
    {
        this->x_ = x;
        return *this;
    }

private:
    int x_{};
};
```

Birçok durumda `this->` açıkça yazılmak zorunda değildir.

### new ve delete

Tek nesne:

```cpp
int *p = new int{42};
delete p;
```

Dizi:

```cpp
int *a = new int[100];
delete[] a;
```

Doğru eşleşme gerekir:

```text
new     -> delete
new[]   -> delete[]
```

### Ham new/delete neden sınırlandırılmalı?

Manuel sahiplik:

- leak,
- double delete,
- exception sırasında kaynak kaybı,
- karmaşık yaşam süresi

sorunlarına açıktır.

Modern C++'ta:

```cpp
std::vector<int>
std::string
std::unique_ptr<T>
std::shared_ptr<T>
```

gibi RAII türleri tercih edilir.

### unique_ptr

Tek sahiplik:

```cpp
auto p = std::make_unique<MyType>();
```

`p` scope dışına çıktığında nesne otomatik silinir.

Kopyalanamaz, taşınabilir.

### shared_ptr

Paylaşılan sahiplik:

```cpp
auto p = std::make_shared<MyType>();
```

referans sayımı kullanır.

Her nesne ilişkisi için `shared_ptr` kullanmak doğru değildir. Sahiplik gerçekten paylaşılıyorsa kullanılmalıdır.

Karşılıklı güçlü referanslar döngü oluşturabilir. Gerekli yerde:

```cpp
std::weak_ptr
```

kullanılır.

### Nesne dizileri

```cpp
std::array<Point, 10> fixed_points;
```

sabit boyut için uygundur.

Dinamik boyut:

```cpp
std::vector<Point> points;
```

ile daha doğal yönetilir.

Ham:

```cpp
Point *p = new Point[n];
```

modern genel uygulama kodunda çoğunlukla gerekli değildir.

## Ünite 4: Fonksiyon ve İşleç Aşırı Yükleme

### Fonksiyon aşırı yükleme

Aynı ad farklı parametre listeleriyle kullanılabilir:

```cpp
int abs_value(int x);
double abs_value(double x);
```

Derleyici çağrıdaki argüman türlerine göre uygun overload'u seçer.

Yalnız dönüş türünün değişmesi yeterli değildir:

```cpp
int f(int);
double f(int);   // geçersiz
```

### Varsayılan argüman

```cpp
void log(std::string_view text, int level = 1);
```

çağrılar:

```cpp
log("başladı");
log("hata", 3);
```

biçiminde olabilir.

Varsayılan argümanlar parametre listesinin uygun sağ tarafında düzenlenmelidir.

### Kurucu aşırı yükleme

```cpp
class Point {
public:
    Point() = default;

    Point(int x, int y)
        : x_{x}, y_{y}
    {
    }

private:
    int x_{};
    int y_{};
};
```

aynı sınıfı farklı başlangıç verileriyle kurmayı sağlar.

### Delege eden kurucu

```cpp
class Point {
public:
    Point()
        : Point{0, 0}
    {
    }

    Point(int x, int y)
        : x_{x}, y_{y}
    {
    }

private:
    int x_;
    int y_;
};
```

başlatma mantığının tekrarını azaltır.

### İşleç aşırı yükleme

Kullanıcı tanımlı türler için birçok işlecin davranışı tanımlanabilir.

Örnek:

```cpp
class Vector2 {
public:
    Vector2(double x, double y)
        : x_{x}, y_{y}
    {
    }

    Vector2 operator+(const Vector2& other) const
    {
        return {x_ + other.x_, y_ + other.y_};
    }

private:
    double x_;
    double y_;
};
```

Kullanım:

```cpp
Vector2 c = a + b;
```

### İşleç aşırı yüklemede tasarım

İşlecin anlamı kullanıcı beklentisine yakın kalmalıdır.

Örneğin:

```text
a + b
```

ifadesinin `a` nesnesini sürpriz biçimde silmesi veya dosyayı kapatması kötü tasarımdır.

Aşırı yükleme sözdizim kolaylığı sağlar, anlam karmaşasını haklı çıkarmaz.

### Karşılaştırma

Modern C++'ta eşitlik ve sıralama işleçleri uygun biçimde tanımlanabilir.

C++20 ile üç yönlü karşılaştırma:

```cpp
operator<=>
```

bazı türlerde karşılaştırma işlemlerini sadeleştirebilir.

### Artırma işleci

Prefix:

```cpp
T& operator++();
```

Postfix:

```cpp
T operator++(int);
```

dummy `int` parametresi iki overload'u ayırır.

## Ünite 5: Kalıtım ve Çok Biçimlilik

### Kalıtım

Bir sınıf başka bir sınıfın arabirim ve davranışının bir bölümünü devralabilir.

```cpp
class Shape {
    ...
};

class Circle : public Shape {
    ...
};
```

Public kalıtım genel olarak:

```text
Circle bir Shape'dir
```

ilişkisini modellemelidir.

Sırf kod tekrarını azaltmak için kalıtım kullanmak uygun olmayabilir. Bileşim çoğu durumda daha esnek çözüm sağlar.

### public kalıtım

Temel sınıfın:

- `public` üyeleri türetilmiş sınıfta public,
- `protected` üyeleri protected

olarak kalır.

`private` üyelere türetilmiş sınıf doğrudan erişemez.

### protected kalıtım

Public ve protected üyeler türetilmiş sınıfta protected hale gelir.

Dış API'de "is-a" ilişkisini sakladığı için genel modellemede daha seyrek kullanılır.

### private kalıtım

Temel sınıfın public ve protected üyeleri türetilmiş sınıfta private olur.

Bu daha çok gerçekleştirim tekniği olarak görülebilir. Çoğu durumda composition daha açık olabilir.

### Kurucu sırası

Türetilmiş nesne oluşturulurken genel sıra:

```text
temel sınıf
↓
üye nesneler
↓
türetilmiş sınıf
```

Yıkım ters sırada olur.

### Çoklu kalıtım

C++ birden fazla temel sınıftan kalıtımı destekler:

```cpp
class C : public A, public B {
};
```

Bu olanak güçlüdür fakat:

- ad belirsizliği,
- diamond problemi,
- karmaşık yaşam döngüsü

oluşturabilir.

Arayüz benzeri küçük soyut temel sınıfların birleştirilmesi daha kontrollü kullanım alanıdır.

### Diamond problemi

```text
    A
   / \
  B   C
   \ /
    D
```

B ve C ayrı ayrı A'dan türetilirse D içinde iki ayrı A alt nesnesi bulunabilir.

Virtual inheritance:

```cpp
class B : virtual public A {};
class C : virtual public A {};
```

tek ortak A alt nesnesi kullanılmasını sağlayabilir.

### Sanal fonksiyon

Çalışma zamanı çok biçimliliği için:

```cpp
class Shape {
public:
    virtual double area() const = 0;
    virtual ~Shape() = default;
};
```

Türetilmiş sınıf:

```cpp
class Circle : public Shape {
public:
    explicit Circle(double r)
        : r_{r}
    {
    }

    double area() const override
    {
        return 3.141592653589793 * r_ * r_;
    }

private:
    double r_;
};
```

### override

```cpp
double area() const override;
```

derleyicinin gerçekten bir temel sınıf sanal işlevinin override edildiğini doğrulamasını sağlar.

Yanlış imza gibi hataları erken yakalar.

### virtual destructor

Polimorfik temel sınıf nesnesi temel sınıf işaretçisi üzerinden silinecekse destructor sanal olmalıdır:

```cpp
virtual ~Base() = default;
```

Aksi halde davranış hatalı olabilir.

### Saf sanal fonksiyon

```cpp
virtual void draw() = 0;
```

sınıfı soyut hale getirir.

Soyut sınıftan doğrudan nesne oluşturulamaz.

### Dinamik dispatch

```cpp
Shape& s = circle;
s.draw();
```

çağrısı nesnenin gerçek dinamik türüne göre uygun override'ı çalıştırır.

Bu **runtime polymorphism**dir.

### Statik çok biçimlilik

C++'ta templates ve overload'lar derleme zamanı çok biçimliliği sağlar.

Örnek:

```cpp
template <typename T>
T max_value(T a, T b)
{
    return a > b ? a : b;
}
```

Bu yapı sanal çağrıdan farklıdır. Uygun kod tür başına derleme sırasında oluşturulur.

## Ünite 6: C++ Giriş Çıkış ve Dosyalar

### Akımlar

C++ I/O sistemi stream soyutlamasına dayanır.

Temel akımlar:

```text
std::cin
std::cout
std::cerr
std::clog
```

### Çıktı

```cpp
std::cout << "Değer: " << value << '\n';
```

`'\n'` yalnız yeni satır ekler.

```cpp
std::endl
```

yeni satırın yanında stream'i flush eder. Her satırda gereksiz `std::endl` kullanmak performansı azaltabilir.

### Girdi

```cpp
int value{};

if (std::cin >> value) {
    ...
}
```

Stream durumunu denetlemek hatalı girdiyi yönetmek için önemlidir.

### Biçimlendirme

```cpp
#include <iomanip>

std::cout
    << std::fixed
    << std::setprecision(2)
    << value;
```

### Dosya yazma

```cpp
#include <fstream>

std::ofstream out{"data.txt"};

if (!out) {
    // hata
}

out << 10 << ' ' << 20 << '\n';
```

Dosya nesnesi RAII sayesinde kapsam sonunda kapanır.

### Dosya okuma

```cpp
std::ifstream in{"data.txt"};

int a{};
int b{};

if (in >> a >> b) {
    ...
}
```

### Satır okuma

```cpp
std::string line;

while (std::getline(in, line)) {
    ...
}
```

### İkili dosyalar

```cpp
std::ofstream out{
    "data.bin",
    std::ios::binary
};
```

Ham nesne belleğini doğrudan kalıcı biçim olarak yazmak C++ için de taşınabilir değildir.

Özellikle sınıflar için:

- vtable işaretçileri,
- padding,
- işaretçiler,
- endian,
- ABI

nedeniyle açık serileştirme gerekir.

### Rastgele erişim

```cpp
stream.seekg(position);
stream.tellg();
stream.seekp(position);
stream.tellp();
```

ile dosya konumu yönetilebilir.

## Ünite 7: C++ Standart Kütüphanesi

### Standart Şablon Kütüphanesi yaklaşımı

C++ standart kütüphanesinde container, iterator ve algoritmalar birlikte çalışır.

Kavramsal model:

```text
Container
   ↓ iterator range
Algorithm
```

Bu ayrım veri yapısı ile algoritmanın gevşek bağlı kalmasını sağlar.

### vector

```cpp
std::vector<int> values{1, 2, 3};
```

özellikleri:

- ardışık bellek,
- rastgele erişim `O(1)`,
- sona ekleme amortize `O(1)`,
- ortada ekleme/silme `O(n)`.

```cpp
values.push_back(4);
values.pop_back();
```

`std::vector`, genel amaçlı değişken boyutlu ardışık veri için çoğu zaman varsayılan container seçimidir.

### array

Sabit boyutlu dizi:

```cpp
std::array<int, 4> values{1, 2, 3, 4};
```

C dizisine benzer ardışık saklama sağlar fakat:

- `size`,
- iterator,
- assignment

gibi standart container olanaklarını sunar.

### list

```cpp
std::list<int>
```

çift yönlü bağlantılı listedir.

Bilinen konumda ekleme ve silme sabit zamanlı olabilir.

Ancak:

- rastgele erişim yoktur,
- her elemanda bağlantı maliyeti vardır,
- cache locality düşüktür.

Bu nedenle `std::list`, `std::vector` yerine otomatik olarak daha verimli değildir.

### deque

```cpp
std::deque<int>
```

iki uçtan büyüyebilen sıra yapısıdır.

Başta ve sonda ekleme/silme verimlidir.

Bellek yerleşimi `vector` gibi tek parça ardışık olmak zorunda değildir.

### stack

```cpp
std::stack<int> stack;
```

LIFO adaptörüdür.

```cpp
stack.push(10);
stack.top();
stack.pop();
```

### queue

```cpp
std::queue<int> queue;
```

FIFO adaptörüdür.

### priority_queue

```cpp
std::priority_queue<int>
```

varsayılan olarak en büyük elemanı tepeye getiren öncelik kuyruğudur.

Heap tabanlı gerçekleştirim yaygındır.

### associative containers

```text
std::set
std::map
std::multiset
std::multimap
```

sıralı ilişkisel container'lardır.

Yaygın gerçekleştirim dengeli ağaçtır.

Tipik arama:

```text
O(log n)
```

### unordered containers

```text
std::unordered_set
std::unordered_map
```

hash tablosu yaklaşımına dayanır.

Ortalama arama:

```text
O(1)
```

olabilir.

Kötü durum garantisi aynı değildir.

### Iterator

Iterator container elemanları üzerinde konum ve dolaşım soyutlamasıdır.

Örnek:

```cpp
for (auto it = values.begin(); it != values.end(); ++it) {
    std::cout << *it << '\n';
}
```

Modern C++'ta range-for daha sade olabilir:

```cpp
for (const auto& value : values) {
    std::cout << value << '\n';
}
```

### Iterator kategorileri

Klasik kategoriler:

- input,
- output,
- forward,
- bidirectional,
- random access,
- contiguous

olarak düşünülür.

Her algoritma her iterator türüyle çalışamaz.

Örneğin rastgele erişim gerektiren algoritma `std::list` iterator'ıyla kullanılamaz.

### find

```cpp
auto it = std::find(values.begin(), values.end(), target);
```

dizilim içinde doğrusal arama yapar.

Bulunamazsa:

```cpp
it == values.end()
```

olur.

### sort

```cpp
std::sort(values.begin(), values.end());
```

random-access iterator gerektirir.

Standart karmaşıklık:

```text
O(n log n)
```

karşılaştırma düzeyindedir.

### count

```cpp
auto n = std::count(
    values.begin(),
    values.end(),
    target
);
```

eşleşen eleman sayısını verir.

### search

Alt dizi araması:

```cpp
std::search(
    sequence.begin(),
    sequence.end(),
    pattern.begin(),
    pattern.end()
);
```

ile yapılabilir.

### transform

```cpp
std::transform(
    input.begin(),
    input.end(),
    output.begin(),
    operation
);
```

her elemana dönüşüm uygular.

Modern C++'ta lambda ile:

```cpp
std::transform(
    values.begin(),
    values.end(),
    result.begin(),
    [](int x) { return x * x; }
);
```

kullanımı doğaldır.

### Lambda

```cpp
auto square = [](int x) {
    return x * x;
};
```

adı olmayan fonksiyon nesnesi oluşturur.

Algoritmalarla kullanımı:

```cpp
std::sort(
    people.begin(),
    people.end(),
    [](const Person& a, const Person& b) {
        return a.age < b.age;
    }
);
```

### ranges

C++20 ve sonrasında ranges kütüphanesi algoritma ve görünüm işlemlerini geliştirir.

Örneğin:

```cpp
std::ranges::sort(values);
```

iterator çiftini açıkça yazma ihtiyacını azaltabilir.

Views:

- filtreleme,
- dönüştürme,
- tembel veri işleme

için kullanılabilir.

Dersin klasik STL container-iterator-algorithm modeli ranges yaklaşımının da temelini oluşturur.

## Ünite 8: Modern C++ Kaynak ve Tür Güvenliği

### Raw pointer sahiplik değildir

Ham işaretçi:

```cpp
T*
```

tek başına nesnenin sahibinin kim olduğunu belirtmez.

Modern tasarımda ayrım açık olmalıdır:

- sahiplik,
- gözlem,
- geçici erişim.

Tek sahiplik:

```cpp
std::unique_ptr<T>
```

Paylaşılan sahiplik:

```cpp
std::shared_ptr<T>
```

Sahip olmayan erişim:

```cpp
T*
T&
std::span<T>
```

gibi türlerle ifade edilebilir.

### std::span

Ardışık veri aralığını sahiplenmeden temsil eder:

```cpp
void process(std::span<const int> values)
{
    for (int x : values) {
        ...
    }
}
```

Bu sayede dizi ve `std::vector` gibi farklı ardışık kaynaklar ortak arabirimle kullanılabilir.

### std::string_view

Sahip olmayan metin görünümü:

```cpp
void print(std::string_view text);
```

gereksiz `std::string` kopyalarını azaltabilir.

Ancak gösterdiği karakterlerin yaşam süresini uzatmaz. Dangling `string_view` oluşturulmamalıdır.

### Exception

C++ hata aktarımı için exception mekanizması sağlar:

```cpp
throw std::runtime_error{"hata"};
```

yakalama:

```cpp
try {
    ...
} catch (const std::exception& e) {
    ...
}
```

RAII, exception kullanılsa da kaynakların doğru serbest bırakılabilmesini sağlar.

### noexcept

Bir fonksiyon:

```cpp
void swap(Type& other) noexcept;
```

ile exception fırlatmayacağını bildirebilir.

Özellikle move operation'larda `noexcept`, standart container optimizasyonlarını etkileyebilir.

### Undefined behavior

Hem C hem C++'ta bazı hatalar "hata kodu üretir" biçiminde tanımlanmaz. Davranış tamamen tanımsız olabilir.

Örnekler:

- dizi sınırı dışı erişim,
- serbest bırakılmış belleğe erişim,
- null işaretçiyi dereference etme,
- signed integer overflow,
- bazı yaşam süresi ihlalleri.

Undefined behavior, yalnız beklenmedik çıktı değil, derleyicinin program hakkında çok farklı optimizasyon varsayımları yapabilmesi anlamına gelir.

### Derleyici uyarıları

Geliştirme sırasında yüksek uyarı düzeyi kullanılmalıdır.

GCC/Clang için örnek:

```text
-Wall
-Wextra
-Wpedantic
-Wconversion
```

Her uyarı mutlak hata değildir, fakat sessiz tür dönüşümleri ve olası kusurları görünür hale getirir.

### Sanitizer

Geliştirme ve testte:

```text
AddressSanitizer
UndefinedBehaviorSanitizer
ThreadSanitizer
```

gibi araçlar:

- bellek taşması,
- use-after-free,
- undefined behavior,
- veri yarışı

gibi hataları bulmada çok değerlidir.

### C ve C++ için güvenli varsayımlar

C'de:

- boyutları açık taşı,
- `gets` kullanma,
- `scanf` ve dosya işlemlerinin dönüşlerini denetle,
- dinamik belleğin sahipliğini açık tut,
- `malloc` çarpımında taşmayı değerlendir,
- işaretçi yaşam süresini takip et.

C++'ta bunlara ek olarak:

- raw `new/delete` yerine RAII,
- C karakter dizisi yerine uygun olduğunda `std::string`,
- dinamik dizi yerine `std::vector`,
- null için `nullptr`,
- sahiplik için smart pointer,
- kopya/move davranışında Rule of Zero,
- polimorfik temelde virtual destructor

tercih edilmelidir.

## C ve C++ Arasındaki Temel Farklar

| Konu | C | C++ |
| --- | --- | --- |
| Temel yaklaşım | Yordamsal ve sistem programlama | Çok paradigmalı |
| Sınıf | Yok | Var |
| Kalıtım | Yok | Var |
| Sanal fonksiyon | Yok | Var |
| Fonksiyon aşırı yükleme | Yok | Var |
| İşleç aşırı yükleme | Yok | Var |
| Reference türü | Yok | Var |
| Template | Yok | Var |
| Exception | Yok | Var |
| Namespace | Yok | Var |
| Dinamik bellek | `malloc/free` | RAII, container, smart pointer, `new/delete` |
| Metin | `char` dizisi | `std::string` ve C dizileri |
| Dinamik dizi | Manuel bellek | `std::vector` |
| Jenerik programlama | Makro / `_Generic` gibi olanaklar | Template ve concepts |
| Standart algoritmalar | Daha sınırlı | Geniş algorithms/ranges kütüphanesi |

Bu tablo dillerden birinin diğerinden genel olarak "daha iyi" olduğu anlamına gelmez.

C:

- ABI sadeliği,
- küçük runtime,
- gömülü sistemler,
- işletim sistemi çekirdeği,
- donanım arabirimi,
- taşınabilir C API

için güçlüdür.

C++:

- büyük performans duyarlı uygulamalar,
- kaynak güvenliği,
- yüksek düzey soyutlama,
- generic programming,
- oyun motorları,
- gerçek zamanlı sistemler,
- masaüstü uygulamaları,
- yüksek performanslı kütüphaneler

için geniş araçlar sunar.

## Bu Çalışmaya Atıf

Köker, M. A. (2014). C++ ile Nesne Yönelimli Programlama. alikoker.com.tr. https://alikoker.com.tr/cpp-ile-nesne-yonelimli-programlama

- BibTeX: https://alikoker.com.tr/cpp-ile-nesne-yonelimli-programlama.bib
- RIS: https://alikoker.com.tr/cpp-ile-nesne-yonelimli-programlama.ris
- CSL-JSON: https://alikoker.com.tr/cpp-ile-nesne-yonelimli-programlama.csl.json
