2018-06-04 01:43:09 +03:00
---
2022-08-01 23:39:47 +03:00
language: C++
2018-06-15 09:17:34 +03:00
lang: tr-tr
2018-09-04 15:59:22 +03:00
filename: learncpp-tr.cpp
2018-06-04 01:43:09 +03:00
contributors:
- ["Steven Basart", "http://github.com/xksteven"]
- ["Matt Kline", "https://github.com/mrkline"]
- ["Geoff Liu", "http://geoffliu.me"]
- ["Connor Waters", "http://github.com/connorwaters"]
- ["Ankush Goyal", "http://github.com/ankushg07"]
- ["Jatin Dhankhar", "https://github.com/jatindhankhar"]
- ["Adem Budak", "https://github.com/p1v0t"]
---
C++
[yaratı cı sı Bjarne Stroustrup'a göre ](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote ),
- "daha iyi bir C" yapmak
- veri soyutlamayı desteklemek
- nesneye yönelik programlamayı deskteklemek
- tipten bağı msı z programlamayı desteklemek
için tasarlanmı ş bir sistem programlama dilir.
Sözdizimi daha yeni dillerden daha zor veya karmaşı k olsa da işlemcinin doğrudan çalı ştı rabileceği
native komutlara derlenerek, donanı m üzerinde (C gibi) sı kı bir kontrol sağlar, bunu yaparken
tipten bağı msı zlı k, exception'lar ve sı nı flar gibi yüksek-seviyeli özellikleri destekler.
Bu hı z ve kullanı şlı lı k C++'ı en çok kullanı lan dillerden biri yapar.
```c++
2018-06-20 02:54:22 +03:00
//////////////////////
2018-06-04 01:43:09 +03:00
// C ile karşı laştı rma
2018-06-20 02:54:22 +03:00
//////////////////////
2018-06-04 01:43:09 +03:00
// C++ _neredeyse_ C'nin bir üstkümesidir, değişken tanı mı , basit tipleri
2018-06-20 02:54:22 +03:00
// ve fonksiyonları için temelde aynı sözdizimini paylaşı r.
2018-06-04 01:43:09 +03:00
// Aynı C gibi, programı n başlangı ç noktası bir integer döndüren
// main fonksiyonudur.
// Bu değer programı n bitiş statüsünü belli eder.
// Daha fazla bilgi için bknz http://en.wikipedia.org/wiki/Exit_status .
int main(int argc, char** argv)
{
// Komut satı rı argümanları C'de olduğu gibi argv ve argc ile geçilir
// argc, argüman sayı sı nı belli eder,
// argv, argümanları belli eden, C-stili string'lerin (char*) dizisidir.
// İlk argüman çağrı lan programı n adı dı r.
// Eğer argümanları umursamı yorsan, argv ve argc kullanı lmayabilir
// int main() gibi
// 0 çı kı ş durumu başarı yı belirtir.
return 0;
}
// Bunlara rağmen C++ aşağı daki noktalarda farklı laşı r:
// C++'ta, karakterler char türündendir
sizeof('c') == sizeof(char) == 1
// C'de, karakterler int türündendir
sizeof('c') == sizeof(int)
// C++ katı bir prototip kuralı na sahiptir
void func(); // fonksiyon argüman kabul etmez
// C'de
void func(); // fonksiyon herhangi bir sayı da argüman kabul edebilir
// C++'da NULL yerine nullptr kullanı lı r
int* ip = nullptr;
// C standard başlı kları başı na "c" eklenip, sondaki .h
// kullanı lmadan C++'ta kullanı labilir
#include <cstdio>
int main()
{
printf("Hello, world!\n");
return 0;
}
//////////////////////////////////
// Fonksiyonun fazladan yüklenmesi
//////////////////////////////////
// C++ herbir fonksiyonun farklı parametereler
// aldı ğı fonksiyon fazladan yüklenmesini desktekler
void print(char const* myString)
{
printf("String %s\n", myString);
}
void print(int myInt)
{
printf("My int is %d", myInt);
}
int main()
{
print("Hello"); // void print(const char*) fonksiyonunu çağı rı r.
print(15); // void print(int) fonksiyonunu çağı rı r.
}
////////////////////////////////
// Default fonksiyon argümanları
2018-06-20 02:54:22 +03:00
////////////////////////////////
2018-06-04 01:43:09 +03:00
// Eğer çağı rı cı tarafı ndan fonksiyona argüman sağlanmamı şsa,
// fonksiyona default argüman verebilirsin
void doSomethingWithInts(int a = 1, int b = 4)
{
// Burada int'lerle birşeyler yap
}
int main()
{
doSomethingWithInts(); // a = 1, b = 4
doSomethingWithInts(20); // a = 20, b = 4
doSomethingWithInts(20, 5); // a = 20, b = 5
}
// Default argümanlar, argüman listesinin sonunda yer almalı .
void invalidDeclaration(int a = 1, int b) // Hata!
{
}
/////////////////////////
// Namespace(İsim uzayı )
/////////////////////////
// Namespace'ler değişken, fonksiyon ve diğer bildirimlerin
// kapsama alanı nı ayı rı r.
// Namespace'ler içiçe geçebilir.
namespace First {
namespace Nested {
void foo()
{
printf("This is First::Nested::foo\n");
}
} // Nested namespace'inin sonu
} // First namespace'inin sonu
namespace Second {
void foo()
{
printf("This is Second::foo\n");
}
}
void foo()
{
printf("This is global foo\n");
}
int main()
{
// Second namespace'i içinideki tüm sembolleri mevcut kapsama alanı na dahil eder.
// Dikkat edersen artı k yalnı zca foo() çağrı sı çalı şmayacaktı r çünkü hangi
// namespace'ten çağrı ldı ğı açı k değildir.
using namespace Second;
Second::foo(); // "This is Second::foo" yazdı rı ı r
First::Nested::foo(); // "This is First::Nested::foo" yazdı rı r
::foo(); // "This is global foo" yazdı rı r.
}
///////////////
// Input/Output
///////////////
// C++'ta input ve output stream'leri kullanı r.
// cin, cout ve cerr,sı rası yla, stdin, stdout, ve stderr'i temsil eder.
// < < araya ekleme ve > > aradan çı karma operatörüdür.
#include <iostream> // I/O stream'lerini dahil etmek için
using namespace std; // Streamler std namespace'i içindedir(standard kütüphane)
int main()
{
int myInt;
// stdout (veya terminal/screen)'ta çı ktı verir
cout << "Enter your favorite number:\n";
// Girdiyi alı r
cin >> myInt;
// cout ayrı ca formatlanabilir
cout << "Your favorite number is " < < myInt << " \n";
// prints "Your favorite number is < myInt > "
cerr < < "Used for error messages";
}
//////////////
// String'ler
/////////////
// String'ler C++'ta nesnedir ve pek çok üye fonksiyonu vardı r
#include <string>
using namespace std; // String'ler de std namespace'i içindedir. (standard kütüphane)
string myString = "Hello";
string myOtherString = " World";
// + eklemek için kullanı ldı r
cout < < myString + myOtherString ; / / " Hello World "
cout < < myString + " You " ; / / " Hello You "
// C++'ta stringler are mutable'dı r (değişebilir).
myString.append(" Dog");
cout < < myString ; / / " Hello Dog "
///////////////////////
// Reference (Referans)
///////////////////////
// C'deki pointer'lara ek olarak
// C++ _reference_ 'lara sahiptir.
// Bunlar bir kere atandı nğı nda tekrardan atanamayan pointer'dı r
// ve null olamaz.
// Değişkenin kendisiyle aynı sözdizimine sahiptir:
// Değerine ulaşmak için * ihtiyaç yoktur ve
// atama için & (address of) kullanı lmaz.
using namespace std;
string foo = "I am foo";
string bar = "I am bar";
string& fooRef = foo; // Bu foo'nun reference'ı nı oluşturur.
fooRef += ". Hi!"; // foo'yu reference'ı üzerinden değiştirir.
cout < < fooRef ; / / " I am foo . Hi ! " yazdı rı r .
// "fooRef"e yeniden atama yapmaz. Bu "foo = bar" denktir ve bu satı rdan sonra
// foo == "I am bar" olur
cout < < & fooRef < < endl ; / / foo ' un adresini yazdı rı r
fooRef = bar;
cout < < & fooRef < < endl ; / / Hala foo ' nun adresini yazdı rı r
cout < < fooRef ; / / " I am bar " yazdı rı r
// fooRef'in adresi aynı kalı r yani hala foo'nun adresidir.
const string& barRef = bar; // bar'a const reference oluşturur
// C'de olduğu gibi, const değerler (pointer'lar ve reference'ler) değiştirilemez.
barRef += ". Hi!"; // Hata, const reference'ler değiştirilemez.
// Kı sa bir ekleme: reference'lere devam etmeden önce, geçici nesne konseptinden
// bahsetmeliyiz. Mesela aşadaki gibi bir kod var:
string tempObjectFun() { ... }
string retVal = tempObjectFun();
// Bu iki satı rda aslı nda ne oluyor:
// - tempObjectFun fonksiyonundan bir string nesnesi dönüyor
// - dönmüş olan nesneyle yeni bir string oluşturuyor
2018-06-20 02:54:22 +03:00
// - dönmüş olan nesne yok ediliyor
2018-06-04 01:43:09 +03:00
// İşte bu dönen nesneye geçici nesne denir. Geçici nesneler fonksiyon nesne
// döndürdüğünde oluşturulur ve ifade işini bitirdiğinde yok edilir (Aslı nda,
// standard'ı n söylediği şey bu ama derleyiciler bu davranı şı değiştirmemize
// izin veriyor. Daha fazla detay için "return value optimization" diye
// aratabilirsin. Sonuç olarak aşağı daki kodda:
foo(bar(tempObjectFun()))
// foo ve bar'ı n varolduğunu kabul ediyoruz, tempObjectFun'dan dönen nesne
// bar'a geçti ve foo çağrı lmadan önce yokedildir.
// Şimdi reference'lara dönelim. "ifadenin sonunda" kuralı nı n bir istisnası
// eğer geçici nesne const reference'a geçildiyse oratya çı kar, bu durumda
// nesnenin ömrü mevcut kapsama alanı na kadar uzar:
void constReferenceTempObjectFun() {
// constRef geçici nesneyi alı r ve bu durum fonksiyonun sonuna kadar geçerlidir.
const string& constRef = tempObjectFun();
...
}
// C++11 ile gelen diğer bir reference geçici nesnelere özeldir. Bu türden birden
// bir tip tanı mlayamazsı n ama aşı rı yüklenme sı rası nda bu tipler öncelik alı r:
void someFun(string& s) { ... } // Regular reference
void someFun(string& & s) { ... } // Geçici nesneye reference
string foo;
someFun(foo); // regular reference'ı çağı rı r
someFun(tempObjectFun()); // geçici reference'ı çağı rı r
/////////////////////
// Enum
/////////////////////
// Enum'lar sabit değerler yapmak için kullanı lı r ve çoğunlukla kodun daha okunaklı
// olması için kullanı lı r
enum ECarTypes
{
Sedan,
Hatchback,
SUV,
Wagon
};
ECarTypes GetPreferredCarType()
{
return ECarTypes::Hatchback;
}
// C++11 ile beraber bir tipi enum'a atamanı n kolay bir yolu var, bu enum'un istenen
// tipe dönüştürmek için kullanı şlı bir yöntem
enum ECarTypes : uint8_t
{
Sedan, // 0
Hatchback, // 1
SUV = 254, // 254
Hybrid // 255
};
void WriteByteToFile(uint8_t InputValue)
{
// Serialize the InputValue to a file
}
void WritePreferredCarTypeToFile(ECarTypes InputCarType)
{
// enum uint8_t tipine dönüştürüldü
WriteByteToFile(InputCarType);
}
// Diğer yandan enum'ları n yanlı şlı kla integer tipini veya diğer enumlara dönüşmesini
// istemiyorsan enum class olarak tanı mlayabilirsin
enum class ECarTypes : uint8_t
{
Sedan, // 0
Hatchback, // 1
SUV = 254, // 254
Hybrid // 255
};
void WriteByteToFile(uint8_t InputValue)
{
// Serialize the InputValue to a file
}
void WritePreferredCarTypeToFile(ECarTypes InputCarType)
{
// ECarTypes, uint8_t tipinde olması na rağmen, "enum class" olarak
// tanı mlandı ğı ndan derlenmeyecektir!
WriteByteToFile(InputCarType);
}
///////////////////////////////////////////
// Sı nı flar ve nesneye yönelik proglamalama
///////////////////////////////////////////
// Sı nı flara(class) ilk örnek
#include <iostream>
// Sı nı fı tanı mla.
// Sı nı flar genelde header (.h veya .hpp) dosyaları nda tanı mlanı r.
class Dog {
// Üye değişkenler ve fonksiyonlar default olarak private'dir.
std::string name;
int weight;
// Aşağı da, "private:" veya "protected:" bulunana kadar
// bütün üyeler public'tir.
public:
// Default constructor
Dog();
// Üye fonksiyon bildirimi (gerçeklenimi aşağı da)
// Dikkat ederseniz using namespace std; yerine
// std::string kullandı k.
// Hiçbir zaman header dosyası nda "using namespace std;" kullanma.
void setName(const std::string& dogsName);
void setWeight(int dogsWeight);
// Nesnenin durumunu değiştirmeyen fonksiyonlar const ile işaretlenmelidir
// Türetilen sı nı flarda fonksiyonu override edebilmek için başı na
// _virtual_ eklenmelidir.
// Fonksiyonlar, performanslar ilgili nedenlerden ötürü default olarak virtual değildir
virtual void print() const;
// Fonksiyonlar class içinde de tanı mlanabilir.
// Bu şekille tanı mlanan fonksiyonlar otomatik olarak inline olur.
void bark() const { std::cout < < name << " barks ! \n"; }
// C++ constructor'ları n yanı nda destructor'da sağlar.
// Bunlar nesne silindiğinde veya scope'un dı şı na çı ktı ğı nda çağrı lı r.
// Bu RAII gibi güçlü paradigmaları etkin kı lar.
// (aşağı da açı klandı )
// Eğer sı nı f kendisinden türetiliyorsa, destructor virtual olmalı dı r,
// eğer virtual değilse, türetilmiş sı nı fı n destructor'ı nesne, ana sı nı f
// referans'ı veya pointer'ı üzerinden yok edildiğinde, çağrı lmayacaktı r.
virtual ~Dog();
}; // class tanı mı nı n sonuda noktalı virgül(;) olmalı dı r.
// Sı nı fı n üye fonksiyonları genelde .cpp dosyaları içinde gerçeklenir.
Dog::Dog()
{
std::cout << "A dog has been constructed\n";
}
// Objects (such as strings) should be passed by reference
// Nesneler (string gibi) reference ile fonksiyonlara geçilmelidir
// Eğer nesneleri değiştirilecekse reference ile fonksiyonlara geçilmelidir,
// değiştirilmeyecekse const reference ile geçilmelidir.
void Dog::setName(const std::string& dogsName)
{
name = dogsName;
}
void Dog::setWeight(int dogsWeight)
{
weight = dogsWeight;
}
// Dikkat edersen "virtual" yalnı zca bildirimde gerekli, tanı mlamada değil.
void Dog::print() const
{
std::cout << "Dog is " < < name << " and weighs " << weight << " kg \n";
}
Dog::~Dog()
{
std::cout << "Goodbye " < < name << " \n";
}
int main() {
Dog myDog; // "A dog has been constructed" yazdı rı r
myDog.setName("Barkley");
myDog.setWeight(10);
myDog.print(); // "Dog is Barkley and weighs 10 kg" yazdı rı r.
return 0;
} // "Goodbye Barkley" yazdı rı r.
// Inheritance(Miras)
// Bu sı nı f, Dog sı nı fı nda public ve protected olan herşeyi miras alı r,
// private olanları da miras alı r ama, public ve protected sı nı flar aracı lı yla
// yapı lmı yorsa, doğrudan erişemez.
class OwnedDog : public Dog {
public:
void setOwner(const std::string& dogsOwner);
// print fonksiyonunun davranı şı nı bütün OwnedDogs sı nı fı için override eder
// (üstünden geçer, kendine uyarlar).
// bknz http://en.wikipedia.org/wiki/Polymorphism_(computer_science)
// override anahtar sözcüpü kullanı lma da olur ama kullanı lması aslı nda bir temel
// temel sı nı f fonksiyonunun üzerinden geçtiğimizi gösterir.
void print() const override;
private:
std::string owner;
};
// Bu arada takip eden .cpp dosyası nda:
void OwnedDog::setOwner(const std::string& dogsOwner)
{
owner = dogsOwner;
}
void OwnedDog::print() const
{
Dog::print(); // Ana dog sı nı fı ndaki print fonksiyonunu çağı rı r
std::cout << "Dog is owned by " < < owner << " \n";
// "Dog is < name > and weights < weight > "
// "Dog is owned by < owner > "
// yazdı rı r
}
/////////////////////////////////////////////////////
// ilk değer atama ve Operatörün fazladan yüklenmesi
/////////////////////////////////////////////////////
// C++ dilinde +, -, *, /, gibi operatörlerin davranı şı nı fazladan yükleyebilirsiniz.
// Bu, operator her kullandı nı ldı ğı nda çağrı lan bir fonksiyon tanı mlaması yla yapı lı r.
#include <iostream>
using namespace std;
class Point {
public:
// Üye değişkenkenlere default değer atanabilir.
double x = 0;
double y = 0;
// Default constructor
Point() { };
Point (double a, double b) :
x(a),
y(b)
{ /* İlk değer atama dı şı nda birşey yapma */ }
// + operatorünün fazladan yükle.
Point operator+(const Point& rhs) const;
// += operatorünü fazladan yükle
Point& operator+=(const Point& rhs);
// - ve -= operatorleri fazladan yüklemek de mantı klı olurdu
// ama kı sa tutmak için burda değinmedik.
};
Point Point::operator+(const Point& rhs) const
{
// yeni bir nokta oluştur ve bunu rhs ile topla
return Point(x + rhs.x, y + rhs.y);
}
Point& Point::operator+=(const Point& rhs)
{
x += rhs.x;
y += rhs.y;
return *this;
}
int main () {
Point up (0,1);
Point right (1,0);
// Bu Point + operatorünü çağı rı r
Point result = up + right;
// "Result is upright (1,1)" yazdı rı r.
cout << "Result is upright (" < < result.x << ',' << result . y << ") \n";
return 0;
}
////////////////////////
// Şablonlar (Templates)
////////////////////////
// Şablonlar C++ dilinde tipten bağı msı z programlama için kullanı lı r.
// Zaten aşina olduğun tipten bağı msı z programlamayla başladı k. Bir tip parametresi
2018-06-20 02:54:22 +03:00
// alan fonksiyon veya sı nı f tanı mlamaı k için:
2018-06-04 01:43:09 +03:00
template< class T >
class Box {
public:
// Bu sı nı fta T, herhangi bir tip için kullanı labilir.
void insert(const T& ) { ... }
};
// Derleme esnası nda derleyici aslı nda, parametreleri yerine konmuş şekilde herbir şablonu üretir,
// bu yüzden sı nı fı n tam tanı mı her çağrı lma sı rası nda var olmak zorundadı r. Bu nedenle şablon sı nı fları nı
// tamamen header dosyaları nda görürsün.
// Stack'ta şablon sı nı fı n bir örneğini oluşturmak için:
Box< int > intBox;
// ve, anladı ğı n gibi, kullanabilirsin:
intBox.insert(123);
// Tabi, şablonları içiçe geçirebilirsin:
Box< Box < int > > boxOfBox;
boxOfBox.insert(intBox);
// C++11'den önce iki '>' arası na boşluk koymak zorundaydı k yoksa sağa kaydı rma
// operatörü olarak algı lanabilirdi.
// Bazen şunu da görebilirsin
// template< typename T >
// 'class' ve 'typename' anahtar sözcükleri çoğunlukla
// birbirlerinin yerine kullanı labilir. Tam açı klama için, bknz.
// http://en.wikipedia.org/wiki/Typename
// (evet, bu anahtar sözcüğün kendi Wikipedia sayfası var).
// Benzer şekilde, bir şablon fonksiyon:
template< class T >
void barkThreeTimes(const T& input)
{
input.bark();
input.bark();
input.bark();
}
// Dikkat edersen tip parametresi hakkı nda birşey belirtilmedi. Derleyici bunları üretecek
// ve her parametre geçişinde tip-kontrolü yapacaktı r, bu nedenle de fonksiyon herhangi bir T
// tipi için çalı şacaktı r!
Dog fluffy;
fluffy.setName("Fluffy")
barkThreeTimes(fluffy); // Üç kere "Fluffy barks" yazdı rı r.
// Şablonun parametresi sı nı f olmak zorunda değildir:
template< int Y >
void printMessage() {
cout < < "Learn C++ in " < < Y < < " minutes ! " < < endl ;
}
// Ve template'i daha etkili kod için dı şarı dan özelleştirebilirsin.
// Tabiki gerçek-dünya kullanı mları nda özelleştirme bunun kadar kolay değildir.
// Dikkat edersen, bütün parametreleri dı ştan özelleştirmiş olsak bile
// hala fonksiyonu (veya sı nı fı ( template olarak tanı mlamamı z gerekli.
template< >
void printMessage< 10 > () {
cout < < "Learn C++ faster in only 10 minutes!" < < endl ;
}
printMessage< 20 > (); // "Learn C++ in 20 minutes!" yazdı rı r
printMessage< 10 > (); // "Learn C++ faster in only 10 minutes!" yazdı rı r
///////////////////////////////////////////////
// İstisnai Durum Yönetimi (Exception Handling)
///////////////////////////////////////////////
// Standard kütüphane bazı istisnai tipler sağlar
// (bknz http://en.cppreference.com/w/cpp/error/exception)
// ama herhangi bir tip de istisnai durum fı rlatabilir
#include <exception>
#include <stdexcept>
// _try_ bloğu içinde fı rlatı lan bütün istisnai durumlar, takip eden, _catch_ ile
// yakalanabilir.
try {
// _new_ kullanarak heap'ten istisnai durumlar için yer ayı rma
throw std::runtime_error("A problem occurred");
}
// istisnai durumlar nesne ise const reference ile yakala
catch (const std::exception& ex)
{
std::cout < < ex.what ( ) ;
}
// Bir önceki _catch_ bloğundan kaçan istisnai durum burda yakala
catch (...)
{
std::cout < < "Unknown exception caught";
throw; // Tekrardan istisnai durum fı rlatı r
}
///////
// RAII
///////
// RAII, "Resource Acquisition Is Initialization" kelimelerinin kı saltması dı r.
// Bu Türkçe, "Kaynak alı mı aynı zamanda ilk değer ataması dı r." olarak çevrilebilir.
// Bunu basitçe constructor ile ayrı lan hafı zanı n destructor ile iade edilmesi olarak
// düşünebiliriz.
// Bunun ne şekilde kullanı şlı olduğunu görmek için
// bir C dosyası nı n, dosya işleme biçimine bakabiliriz:
void doSomethingWithAFile(const char* filename)
{
// Başlangı çta herşeyin yolunda gittiğini düşünelim
FILE* fh = fopen(filename, "r"); // Dosyayı okuma modunda aç
doSomethingWithTheFile(fh);
doSomethingElseWithIt(fh);
fclose(fh); // Dosyayı kapat
}
// Malesef hatalarla başa çı kmaya çalı şı rken işler hı zlı ca karmaşı klaşı r.
// Mesela fopen'ı n başarı sı z olduğunu varsayalı m, ve doSoomethingWithTheFile ve
// doSomethingWithIt hata kodları gönderdi.
// (İstisnai durumlar yonetimi, hata koduna tercih ediler bir yöntemdir, ama bazı
// programcı lar, özellikle C arkaplanı olanlar, aynı fikirde değildir.
// Bu durumda her bir fonksiyon çağrı sı nı kontrol etmeli ve bir problem oluştuysa
// dosyayı kapatmalı yı z.
bool doSomethingWithAFile(const char* filename)
{
FILE* fh = fopen(filename, "r"); // Dosyayı okuma modunda aç
if (fh == nullptr) // Başarı sı z olma durumunda dönen değer null olur
return false; // Başarı sı z olma durumunu çağı rı cı ya bildir
// Başarı sı z olma durumunda her iki fonksiyonun da false döndürdüğünü kabul edelim
if (!doSomethingWithTheFile(fh)) {
fclose(fh); // Dosyayı kapatalı m, akı ntı olması n.
return false; // Hatayı bildir
}
if (!doSomethingElseWithIt(fh)) {
fclose(fh); // Dosyayı kapatalı m, akı ntı olması n.
return false; // Hatayı bildir
}
fclose(fh); // Dosyayı kapat
return true; // Başarı durumunu ifade eder
}
// C programcı ları biraz goto kullanarak bu durumu temizler
bool doSomethingWithAFile(const char* filename)
{
FILE* fh = fopen(filename, "r");
if (fh == nullptr)
return false;
if (!doSomethingWithTheFile(fh))
goto failure;
if (!doSomethingElseWithIt(fh))
goto failure;
fclose(fh); // Dosyayı kapat
return true; // Başarı durumunu ifade eder
failure:
fclose(fh);
return false; // Hatayı bildir
}
// Eğer fonksiyon istisnai durum yönetimi araçları nı kullanı rsa
// işler daha temiz olur ama hala en iyi durumun altı nda kalı r.
void doSomethingWithAFile(const char* filename)
{
FILE* fh = fopen(filename, "r");
if (fh == nullptr)
throw std::runtime_error("Could not open the file.");
try {
doSomethingWithTheFile(fh);
doSomethingElseWithIt(fh);
}
catch (...) {
fclose(fh); // Hata durumunda dosyayı kapattı ğı ndan emin ol
throw; // Sonra, tekrardan istisnai durum fı rlat
}
fclose(fh); // Dosyayı kapat
// Herşey başarı lı
}
// Şimdi aynı şeyi C++'ı n dosya stream sı nı fı yla (fstream) karşı laştı ralı m
// fstream, dosyayı kapatmak için kendi destructor'ı nı kullanı r.
// Destructor'ı n, nesne scope dı şı na çı ktı ğı nda otomatik olarak çağrı ldı ğı nı
// hatı rlayı n.
void doSomethingWithAFile(const std::string& filename)
{
std::ifstream fh(filename); // Dosyayı aç
// Dosyayla birşeyler yap
doSomethingWithTheFile(fh);
doSomethingElseWithIt(fh);
} // Dosya, destructor tarafı ndan otomatik olarak kapatı ldı
// Bunun _çok büyük_ avantajları var:
// 1. Ne olursa olursun,
// kaynak (bu örnekte dosya tutucusu) temizlenecektir.
// Destructor doğru yazı ldı ğı nda,
// Tutucuyu kapatmayı unutma ve kaynak akı ntı sı _imkansı z_dı r.
// 2. Kodun çok daha temiz olduğuna dikkat edin.
// Destructor, dosyayı kapatma işini, endilenmemize gerek kalmadan
// arka planda halleder.
// 3. Kod, istisnai durumlara karşı korunaklı dı r.
// İstisnai durum fonksiyonun herhangi bir yerinde fı rlatı labilir ve
// temizleme işi gene de yapı lı r.
// Bütün C++ kodu deyimleri RAII prensibini tüm kaynakları için kullanı r.
// Ek örnekler şunlardı r:
// - unique_ptr ve shared_ptr ile hafı za kullanı mı
// - Tutucular - standard kütüphane linked list,
// vector (yani kendiliğinden boyu ayarlanan dizi), hash map vs.
// scope'un dı şı na çı ktı ğı nda içerini otomatik olarak yok eden tüm yapı lar.
// - lock_guard ve unique_lock kullanan mutex'ler
///////////////////////////////////////
// Lambda İfadeleri (C++11 ve yukarı sı )
///////////////////////////////////////
// lambda'lar, tam olarak çağrı ldı ğı yerde bir anonim fonksiyon tanı mlamak
// veya fonksiyona argüman geçmek için uygun bir yoldur.
// Mesela, pair'lardan oluşan bir vector'u, pair'ı n ikinci değerine
// göre sı ralamak isteyelim
vector< pair < int , int > > tester;
tester.push_back(make_pair(3, 6));
tester.push_back(make_pair(1, 9));
tester.push_back(make_pair(5, 0));
// sort fonksiyonuna üçüncü argüman olarak lambda ifadesini geç
// sort, < algorithm > başlı ğı nda tanı mlı
sort(tester.begin(), tester.end(), [](const pair< int , int > & lhs, const pair< int , int > & rhs) {
return lhs.second < rhs.second ;
});
// Lambda ifadesinin söz dizimine dikkat edin,
// lambda'daki [], değişkenleri "tutmak" için kullanı lı r
// "Tutma listesi", fonksiyon gövdesinde nelerin, ne şekilde erişilebilir olduğunu tanı mlar
// Şunlardan biri olabilir:
// 1. bir değer : [x]
2018-06-20 02:54:22 +03:00
// 2. bir referans : [& x]
// 3. mevcut scope içindeki herhangi bir değişkene referans ile [& ]
// 4. 3 ile aynı , ama değer ile [=]
2018-06-04 01:43:09 +03:00
// Mesela:
vector< int > dog_ids;
// number_of_dogs = 3;
for(int i = 0; i < 3 ; i + + ) {
dog_ids.push_back(i);
}
int weight[3] = {30, 50, 10};
// Mesela dog_ids vector'unu dog'ları n ağı rlı kları na göre sı ralamak isteyelim
// Yani en sonunda şöyle olmalı : [2, 0, 1]
// Burada lambda ifadesi oldukça kullanı şlı dı r
sort(dog_ids.begin(), dog_ids.end(), [&weight ](const int &lhs, const int &rhs ) {
return weight[lhs] < weight [ rhs ] ;
});
// Dikkat edersen "weight" dizisini referans ile aldı k.
// C++'da lambdalar hakkı nda daha fazla bilgi için : http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11
//////////////////////////////////
// Akı llı For (C++11 ve yukarı sı )
//////////////////////////////////
// Akı llı for döngüsünü bir tutucuyu dolaşmak için kullanabilirsin
int arr[] = {1, 10, 3};
for(int elem: arr){
cout < < elem < < endl ;
}
// Tutucunun elemanları nı n tipi için endişe etmeden "auto" kullanabilirsin
// Mesela:
for(auto elem: arr) {
// arr dizisinin elemanları yla ilgili bir şeyler yap
}
2018-06-20 02:54:22 +03:00
////////////////
2018-06-04 01:43:09 +03:00
// Güzel Şeyler
2018-06-20 02:54:22 +03:00
////////////////
2018-06-04 01:43:09 +03:00
// C++ dilinin bakı ş açı sı yeni başlayanlar için (hatta dili iyi bilenler için bile)
// şaşı rtı cı olabilir.
// Bu bölüm, ne yazı k ki, büyük ölçüde tam değil; C++ kendi ayağı na ateş edilebilecek kolay
// dillerden biridir.
// private metodları override edebilirsin!
class Foo {
virtual void bar();
};
class FooSub : public Foo {
virtual void bar(); // Foo::bar fonksiyonu override edilir!
};
// 0 == false == NULL (çoğu zaman)!
bool* pt = new bool;
*pt = 0; // 'pt'nin gösterdiği değere false atar.
pt = 0; // 'pt'ye null pointer atar. Her iki satı r uyarı sı z derlenir.
// nullptr'ı n bu meselenin bazı ları nı çözmesi beklenmiştir:
int* pt2 = new int;
*pt2 = nullptr; // Derlenmez.
pt2 = nullptr; // pt2'ye null atar.
// bool tipleri için bir istisna vardı r.
// Bu null pointer'ları if(!ptr) ile test etmek içindir.
// ama sonuç olarak bir bool değerine nullptr atayabilirsin!
*pt = nullptr; // '*pt' değeri bir boll olması na rağmen, hala derlenir!
// '=' != '=' != '='!
// Calls Foo::Foo(const Foo& ) or some variant (see move semantics) copy
// Foo::Foo(const Foo& ) çağrı sı nı veya kopyalama constructor'ı nı n bir çeşidinin çağrı sı nı yapar(taşı ma semantiklerine bknz.)
Foo f2;
Foo f1 = f2;
// Foo::operator=(Foo& ) çağrı sı nı yapar.
Foo f1;
f1 = f2;
///////////////////////////////////////
// Tuple (C++11 ve yukarı sı )
///////////////////////////////////////
#include<tuple>
// Ana fikir olarak, Tuple, eski veri yapı ları na (C'deki struct'lar) benzer ama isimli veri üyeleri yerine
// elemanları na tuple içindeki sı rası na göre erişilir.
// Tuple'ı inşa ederek başlayalı m
// değişkenleri tuple içinde paketliyoruz
auto first = make_tuple(10, 'A');
const int maxN = 1e9;
const int maxL = 15;
auto second = make_tuple(maxN, maxL);
// 'first' tuple'ı nı n değerlerini yazdı rma
cout < < get < 0 > (first) << " " < < get < 1 > (first) << "\n"; // 10 A yazdı rı r
// 'second' tuple'ı nı n değerlerini yazdı rma
cout < < get < 0 > (second) << " " < < get < 1 > (second) << "\n"; // 1000000000 15 yazdı rı r
// Değişkenleri tuple'dan çı karma
int first_int;
char first_char;
tie(first_int, first_char) = first;
cout < < first_int << " " << first_char << " \n"; // 10 A yazdı rı r
// Ayrı ca şu şekide de tuple oluşturabiliriz.
tuple< int , char , double > third(11, 'A', 3.14141);
// tuple_size, tuple'daki eleman sayı sı nı (constexpr olarak) döndürür
cout < < tuple_size < decltype ( third ) > ::value << "\n"; // 3 yazdı rı r
// tuple_cat, tuple'daki tüm elemanları aynı sı rada birleştirir.
auto concatenated_tuple = tuple_cat(first, second, third);
// concatenated_tuple = (10, 'A', 1e9, 15, 11, 'A', 3.14141) olur
cout < < get < 0 > (concatenated_tuple) << "\n"; // 10 yazdı rı r
cout < < get < 3 > (concatenated_tuple) << "\n"; // 15 yazdı rı r
cout < < get < 5 > (concatenated_tuple) << "\n"; // 'A' yazdı rı r
/////////////////////
// Tutucular
/////////////////////
// Tutucular veya Standard Şablon Kütüphanesi(STL) önceden tanı mlanmı ş şablonlar sunar.
// Bunlar elemanları için ayrı lan hafı za alanı nı yönetir
// ve onlara erişim ve değiştirmek için üye fonksiyonlar sağlar
// Bazı tutucular şunlardı r:
// Vector (Dinamik Dizi)
// koşma anı nda nesne dizisi veya list oluşturmamı zı sağlar
#include <vector>
string val;
vector< string > my_vector; // vector'ü tanı mla
cin >> val;
my_vector.push_back(val); // val değerini my_vector vectörüne push edecektir
my_vector.push_back(val); // val değerini yeniden push edecektir (şu an iki elemanı var)
// vector içinde dolaşmak için iki seçenek var:
// ya klasik döngüyle (0. index'ten son index'e kadar iterasyon yaparak)
for (int i = 0; i < my_vector.size ( ) ; i + + ) {
cout < < my_vector [ i ] < < endl ; / / vector ' ün elemanları na uşamak için [ ] operatörünü kullanabiliriz
}
// ya da iteratör kulllanarak:
vector< string > ::iterator it; // vector için iterator tanı mla
for (it = my_vector.begin(); it != my_vector.end(); ++it) {
cout < < *it < < endl ;
}
// Set(Küme)
// Set'ler benzersiz(unique) elemanları belirli bir sı rada saklayan tutuculardı r.
// Set, benzersiz değerleri, herhangi bir fonksiyon veya kod gerektirmeksizin, sı ralı olarak
#include<set>
set< int > ST; // int tipi için set tanı mlar
ST.insert(30); // ST kümesini 30 değerini dahil eder
ST.insert(10); // ST kümesini 10 değerini dahil eder
ST.insert(20); // ST kümesini 20 değerini dahil eder
ST.insert(30); // ST kümesini 30 değerini dahil eder
// Şimdi kümedeki elemanlar aşağı daki gibidir
// 10 20 30
// Bir eleman silmek için:
ST.erase(20); // 20 değerine sahip elemanı siler
// Set ST: 10 30
// Iterator kullanarak Set içinde iterasyon yapmak için:
set< int > ::iterator it;
for(it=ST.begin();it< ST.end ( ) ; it + + ) {
cout < < *it < < endl ;
}
// Output:
// 10
// 30
// Tutucuyu tamamen silmek için Tutucu_Adi.clear() kullanı rı z
ST.clear();
cout < < ST.size ( ) ; / / ST kümesinin eleman sayı sı ( size ) nı yazdı rı r .
// Output: 0
// NOTE: Aynı elemanlari içerebilen kümle için multiset kullanı rı z
// Map(Harita)
// Map, elemanları anahtar değer, haritalanmı ş değer şeklinde özel bir sı rada saklar.
// anahtar_değer -> haritalanmı ş_değer
#include<map>
map< char , int > mymap; // Anahtar char ve değer int olacak şekilde map tanı mlar
mymap.insert(pair< char , int > ('A',1));
// 1 değeri için A anahtar değerini ekler
mymap.insert(pair< char , int > ('Z',26));
// 26 değeri için Z anahtar değerini ekler
// Map'te dolaşma
map< char , int > ::iterator it;
for (it=mymap.begin(); it!=mymap.end(); ++it)
std::cout < < it- > first << "->" < < it- > second << '\n';
// Output:
// A->1
// Z->26
// Anahtar'a atanmı ş değeri bulmak için
it = mymap.find('Z');
cout < < it- > second;
// Output: 26
/////////////////////////////////////////////
// Mantı ksal ve Bit seviyesindeki operatörler
/////////////////////////////////////////////
// Pek çok C++ operatörleri diğer dillerdekiyle aynı dı r
// Mantı ksal operatörler
// C++, bool ifadelerinde Kı sa-devre değerlendirmesini kullanı r yani ikinci argüman yalnı zca ilk argüman
// ifadenin değerine karar vermek için yeterli değilse çalı ştı rı lı r
true && false // **mantı ksal ve** işlemi yapı lı r ve yanlı ş sonucu üretilir
true || false // **mantı ksal veya** işlemi yapı lı r ve true sonucu üretilir
! true // **mantı ksal değil** işlemi yapı lı r ve yalnı ş sonucu üretilir
// Sembolleri kullanmak yerine onlara karşı lı k gelen anahtar kelimeler kullanı labilir
true and false // **mantı ksal ve** işlemi yapı lı r ve yanlı ş sonucu üretilir
true or false // **mantı ksal veya** işlemi yapı lı r ve true sonucu üretilir
not true // **mantı ksal değil** işlemi yapı lı r ve yalnı ş sonucu üretilir
// Bit seviyesindeki operatörler
// ** << ** Sola kaydı rma operatörü
// < < bitleri sola kaydı rı r
4 < < 1 / / 4 ' ün bitlerini 1 sola kaydı rı r ve 8 sonucunu verir
// x < < n , x * 2 ^ n olarak düşünülebilir
// ** >>** Sağa kaydı rma operatörü
// >> bitleri sağa kaydı rı r
4 >> 1 // 4'ün bitlerini 1 sağa kaydı rı r ve 2 sonucunu verir
// x >> n, x / 2^n olarak düşünülebilir
~4 // Bit seviyesinde değil işlemini gerçekleştirir
4 | 3 // Bit seviyesinde veya işlemini gerçekleştirir
4 & 3 // Bit seviyesinde ve işlemini gerçekleştirir
4 ^ 3 // Bit seviyesinde xor işlemini gerçekleştirir
// Eşdeğer anahtar kelimeler
compl 4 // Bit seviyesinde değil işlemini gerçekleştirir
4 bitor 3 // Bit seviyesinde veya işlemini gerçekleştiri
4 bitand 3 // Bit seviyesinde ve işlemini gerçekleştirir
4 xor 3 // Bit seviyesinde xor işlemini gerçekleştirir
```
2024-04-06 18:33:50 +03:00
2018-06-04 01:43:09 +03:00
İleri okuma:
2018-10-14 03:07:43 +03:00
* Güncel bir referans [CPP Reference ](http://cppreference.com/w/cpp ) adresinde bulunabilir.
* Ek kaynaklar [CPlusPlus ](http://cplusplus.com ) adresinde bulunabilir.
2018-10-14 03:21:14 +03:00
* Dilin temellerini ve kodlama ortamı nı belirleyen bir öğretici [TheChernoProject - C ++ ](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb ) adresinde bulunabilir.