2018-06-04 01:43:09 +03:00
|
|
|
|
---
|
|
|
|
|
language: c++
|
2018-06-15 09:17:34 +03:00
|
|
|
|
lang: tr-tr
|
2018-06-04 01:43:09 +03:00
|
|
|
|
filename: learncpp.cpp
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
İleri okuma:
|
|
|
|
|
|
|
|
|
|
Güncel bir referans
|
|
|
|
|
<http://cppreference.com/w/cpp> adresinde bulunabilir
|
|
|
|
|
|
|
|
|
|
Ek kaynaklar <http://cplusplus.com> adresinde bulunabilir
|