Derinlemesine Erişim Belirleyiciler
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 35 / 104.
Artık üç erişim belirleyicisini anladığına göre, aynı sınıftan birden fazla nesnen olduğunda nasıl davrandıklarını inceleyelim. Yaygın bir yanlış kanı, private'ın "yalnızca bu nesne" anlamına geldiğidir; oysa aslında "yalnızca bu sınıf" anlamına gelir.
Aynı sınıfa ait nesneler birbirlerinin özel üyelerine erişebilir:
class Person {
std::string secret;
public:
Person(std::string s) : secret(s) {}
void readSecret(const Person& other) {
// Başka bir nesnenin private üyesine erişmek - izin veriliyor!
std::cout << other.secret;
}
};Bu, erişim denetiminin nesne düzeyinde değil, sınıf düzeyinde uygulanması sayesinde çalışır. readSecret yöntemi Person sınıfının bir parçasıdır; bu nedenle herhangi bir Person nesnesinin özel üyelerine erişebilir. Bu tasarım, kopya oluşturucular ve karşılaştırma işleçleri gibi işlemlerin diğer nesnelerin iç durumuyla çalışmasını sağlar.
Bir sınıf içinde erişim belirleyicileri arasında birden çok kez geçiş de yapabilirsiniz:
class Mixed {
public:
void publicMethod1();
private:
int privateData;
public:
void publicMethod2(); // Tekrar public
private:
void privateHelper(); // Tekrar private
};Bu geçerli bir C++ kodu olsa da okunabilirlik açısından üyeleri erişim düzeyine göre gruplandırmak genellikle daha iyidir. Çoğu stil kılavuzu, public üyelerin (sınıf arayüzünü oluşturdukları için) önce, ardından protected ve sonra private üyelerin listelenmesini önerir.
Görev
KolayAynı sınıftaki nesnelerin birbirlerinin private üyelerine nasıl erişebileceğini gösteren bir cüzdan karşılaştırma sistemi oluşturalım. Bu, C++ erişim denetimiyle ilgili önemli bir içgörüdür: erişim denetimi nesne düzeyinde değil, sınıf düzeyinde uygulanır.
Kodunu düzenlemek için iki dosya oluşturacaksın:
Wallet.h: Özel finansal verileri saklayan, ancak cüzdanların birbirleriyle karşılaştırılmasına izin veren birWalletsınıfı tanımla. Sınıfın şunlara sahip olmalı:- Özel üyeler:
ownerName(string) vebalance(double) - Sahibin adını ve başlangıç bakiyesini alan bir kurucu
- Sahibin adını döndüren bir public getter
getOwnerName() - Bu cüzdanın bakiyesini başka bir cüzdanın private bakiyesiyle karşılaştıran ve bu cüzdanda daha fazla para varsa
hasMoreThan(const Wallet& other)döndüren birtruemetodu - Her iki cüzdanın private bakiyelerinin toplamını döndüren bir
combinedBalance(const Wallet& other)metodu - Bu cüzdandaki parayı başka bir cüzdana aktaran bir
transferTo(Wallet& other, double amount)metodu. Bu metot, her iki cüzdanın private bakiyesini doğrudan değiştirmeli (yalnızca miktar pozitifse ve bu cüzdanın bakiyesini aşmıyorsa)
- Özel üyeler:
main.cpp: Nesneler arası private üye erişimini göster. Girdiden iki sahip adı ve iki bakiye oku (dört satır: name1, balance1, name2, balance2), ardından:- Girdi değerleriyle iki
Walletnesnesi oluştur "Combined wealth: $<amount>"kullanarakcombinedBalance()yazdır- Cüzdanları karşılaştır ve bakiyesi daha yüksek olan sahibin adı için
"<name> has more money"yazdır (hasMoreThan()kullanarak bunu belirle) 100.0kullanarak ilk cüzdandan ikinci cüzdanatransferTo()aktar"After transfer:"yazdır"Combined wealth: $<amount>"ifadesini tekrar yazdır (değişmemiş olmalı)- Tekrar karşılaştır ve
"<name> has more money"yazdır (sonuç değişmiş olabilir)
- Girdi değerleriyle iki
Buradaki temel kavram, hasMoreThan() ve transferTo() gibi metotların başka bir Wallet nesnesinin private balance üyesine doğrudan erişebilmesidir: getter'lara gerek yoktur. Bu, C++'ta erişim denetiminin sınıf tabanlı olması sayesinde çalışır: Wallet sınıfının içindeki herhangi bir kod, herhangi bir Wallet nesnesinin private üyelerine erişebilir.
Tüm parasal değerleri std::fixed içindeki std::setprecision(2) ve <iomanip> kullanarak iki ondalık basamakla biçimlendir. Bakiye girdilerini std::stod() kullanarak dönüştür.
Kendin dene
#include <iostream>
#include <string>
#include <iomanip>
#include "Wallet.h"
using namespace std;
int main() {
// Girdiyi oku: name1, balance1, name2, balance2
string name1, name2;
string balanceStr1, balanceStr2;
getline(cin, name1);
getline(cin, balanceStr1);
getline(cin, name2);
getline(cin, balanceStr2);
double balance1 = stod(balanceStr1);
double balance2 = stod(balanceStr2);
// Parasal değerler için çıktı biçimlendirmesini ayarla
cout << fixed << setprecision(2);
// TODO: Girdi değerleriyle iki Wallet nesnesi oluştur
// TODO: Print combined wealth using combinedBalance()
// Format: "Combined wealth: $<amount>"
// TODO: Compare wallets using hasMoreThan() and print who has more money
// Format: "<name> has more money"
// TODO: transferTo() kullanarak ilk cüzdandan ikinciye 100.0 aktar
// TODO: Print "After transfer:"
// TODO: Print combined wealth again
// TODO: Compare again and print who has more money
return 0;
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1OOP Temelleri
Harici DosyalarC++ Build ve DerlemeBaşlık Dosyaları ve Kaynak DosyalarıAd Alanları ve KapsamC++'ta OOP'ye GirişSınıflar ve Nesneler'this' İşaretçisiMetotlar (Üye Fonksiyonlar)Öznitelikler (Veri Üyeleri)Ctor ve Dtor TemelleriÖzet - Basit Hesap Makinesi4Sınıf Özellikleri
Örnek ve Statik ÜyelerGetter ve Setter MetotlarıConst Üye FonksiyonlarMutable Anahtar KelimesiStatik Metotlar ve DeğişkenlerFriend Fonksiyonlar ve SınıflarÖzet - Banka Hesabı Yöneticisi7Kalıtım
Temel KalıtımKalıtım Erişim SeviyeleriCtor ve Dtor Çağrılma SırasıMetot Geçersiz KılmaSanal Fonksiyonlar ve VTableÇoklu KalıtımSanal KalıtımÖzet - Çalışan Hiyerarşisi10STL Genel Bakış
STL Genel Bakış ve FelsefesiSTL KonteynerleriİteratörlerSTL AlgoritmalarıFunctor'lar ve Lambda İfadeleriÖzet - Kelime Frekansı13Tasarım Kalıpları 1. Bölüm
Tasarım Kalıplarına GirişSingleton KalıbıFactory ve Abstract FactoryBuilder KalıbıObserver KalıbıStrategy Kalıbı2Bellek Yönetimi
Stack ve Heap Bellekİşaretçiler ve ReferanslarDinamik Bellek (new/delete)C++'ta Akıllı İşaretçilerC++'ta RAIIÖzet - Dinamik Dizi Yöneticisi5Kapsülleme
C++'da Erişim BelirleyicilerDerinlemesine Erişim BelirleyicilerBilgi GizlemeStruct vs Classİç İçe ve Dahili SınıflarÖzet - Öğrenci Kayıt Sistemi8Çok Biçimlilik
Derleme ve Çalışma Zamanı Çok BiçimliliğiFonksiyon Aşırı YüklemeSanal Fonksiyonlara Yeniden BakışSaf Sanal FonksiyonlarSoyut SınıflarC++'ta Arayüz TasarımıDynamic Casting ve RTTIÖzet - Şekil Hesaplayıcı3Yapıcılar ve Yıkıcılar
Varsayılan YapıcıParametreli YapıcıKopya YapıcıTaşıma YapıcısıYapıcı İlklendirme ListeleriTemsilci YapıcılarYıkıcılara Derinlemesine BakışÜç / Beş / Sıfır KuralıÖzet - String Sınıfı6Operatör Aşırı Yükleme
Operatör Aşırı Yüklemeye GirişAritmetik Operatör Aşırı YüklemeKarşılaştırma Operatörü Aşırı YüklemeStream OperatörleriAtama Operatörü Aşırı Yükleme[] ve () Operatör Aşırı YüklemeTip Dönüşüm OperatörleriÖzet - Matris Sınıfı9Şablonlar
Fonksiyon ŞablonlarıSınıf ŞablonlarıŞablon ÖzelleştirmeVariadic ŞablonlarSFINAE ve Type Traits TemelleriÖzet - Generic KonteynerKendi başına pratik yap: Online C++ derleyicisi