Classes, Structs & Encapsulation
Understand the difference between struct and class, access specifiers, encapsulation, const member functions, static members, and modern aggregate initialization.
What Is a Class?
Μια κλάση στο C++ είναι ένας τύπος που ορίζεται από το χρήστη που ομαδοποιεί δεδομένα (μεταβλητές μέλους) και λειτουργίες σε αυτά τα δεδομένα (συναρτήσεις μέλους) σε μια ενιαία μονάδα. Αυτή η ομαδοποίηση ονομάζεται ενθυλάκωση — ένας από τους τέσσερις πυλώνες του OOP.
Η βασική ιδέα είναι ότι μια κλάση ορίζει μια αμετάβλητη: ένα σύνολο κανόνων που πρέπει πάντα να ισχύουν για την εσωτερική της κατάσταση. Για παράδειγμα, μια κλάσηDateμπορεί να απαιτεί ο μήνας να είναι πάντα μεταξύ 1 και 12. Η ενθυλάκωση σάς επιτρέπει να επιβάλλετε αυτά τα αμετάβλητα ελέγχοντας την πρόσβαση στην εσωτερική κατάσταση.
struct vs class
Στο C++, ταstructκαιclassείναι σχεδόν πανομοιότυπα. Η μόνη διαφορά είναι ο προεπιλεγμένος προσδιοριστής πρόσβασης: Τοstructορίζει τοpublicαπό προεπιλογή, ενώ τοclassτοprivate. Σύμβαση: χρησιμοποιήστε τοstructγια απλά συγκεντρωτικά δεδομένα, τοclassόταν έχετε αμετάβλητα να διατηρήσετε.
#include <iostream>
#include <string>
// struct: members are public by default
struct Point {
double x; // public
double y; // public
};
// class: members are private by default
class BankAccount {
std::string owner; // private
double balance; // private
public:
BankAccount(const std::string& name, double initial)
: owner{name}, balance{initial} {}
double get_balance() const { return balance; }
void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
};
int main() {
Point p{3.0, 4.0}; // aggregate initialization
std::cout << p.x << ", " << p.y << '\n';
BankAccount acct{"Alice", 1000.0};
acct.deposit(500.0);
std::cout << acct.get_balance() << '\n'; // 1500
// acct.balance = -999; // ERROR: private member
return 0;
}Access Specifiers & this Pointer
Το C++ παρέχει τρία επίπεδα πρόσβασης: public (όποιος έχει πρόσβαση), private (μόνο η τάξη και οι φίλοι της) και protected (η τάξη, οι φίλοι της και οι παράγωγες κλάσεις). Ο δείκτηςthisείναι ένας σιωπηρός δείκτης στο τρέχον αντικείμενο που είναι διαθέσιμο μέσα σε κάθε συνάρτηση μη στατικού μέλους.
#include <iostream>
#include <string>
class Employee {
private:
std::string name_;
int id_;
protected:
double salary_; // accessible to derived classes
public:
Employee(const std::string& name, int id, double salary)
: name_{name}, id_{id}, salary_{salary} {}
// const member function: promises not to modify the object
const std::string& get_name() const { return name_; }
int get_id() const { return id_; }
// 'this' pointer usage — return *this for method chaining
Employee& set_name(const std::string& name) {
this->name_ = name; // 'this->' disambiguates
return *this;
}
Employee& set_id(int id) {
this->id_ = id;
return *this;
}
void print() const {
std::cout << "Employee{" << name_ << ", #" << id_
<< ", $" << salary_ << "}\n";
}
};
int main() {
Employee e{"Bob", 42, 75000.0};
e.set_name("Robert").set_id(43); // method chaining via *this
e.print(); // Employee{Robert, #43, $75000}
return 0;
}Στατικά Μέλη & φίλος
Τα στατικά μέλη ανήκουν στην κλάση, όχι σε καμία περίπτωση. Χρησιμοποιήστε τα για κοινές λειτουργίες κατάστασης ή βοηθητικές λειτουργίες. Η λέξη-κλειδί friend παραχωρεί μια συνάρτηση που δεν είναι μέλος ή μια άλλη κλάση πρόσβαση σε ιδιωτικά μέλη — χρησιμοποιήστε με φειδώ, καθώς διακόπτει την ενθυλάκωση.
#include <iostream>
class Widget {
int value_;
// C++17: inline static — define in header, no .cpp needed
inline static int count_ = 0;
public:
explicit Widget(int v) : value_{v} { ++count_; }
~Widget() { --count_; }
static int get_count() { return count_; }
// friend function can access private members
friend std::ostream& operator<<(std::ostream& os, const Widget& w);
};
std::ostream& operator<<(std::ostream& os, const Widget& w) {
return os << "Widget(" << w.value_ << ')'; // accesses private value_
}
int main() {
Widget a{10}, b{20};
std::cout << Widget::get_count() << '\n'; // 2
std::cout << a << '\n'; // Widget(10)
{
Widget c{30};
std::cout << Widget::get_count() << '\n'; // 3
}
std::cout << Widget::get_count() << '\n'; // 2
return 0;
}Συγκεντρωτική εκκίνηση και καθορισμένοι αρχικοποιητές (C++20)
Ένα συγκεντρωτικό είναι μια κλάση ή δομή χωρίς κατασκευαστές δηλωμένους από το χρήστη, χωρίς ιδιωτικά/προστατευμένα μη στατικά μέλη δεδομένων, χωρίς εικονικές συναρτήσεις και χωρίς κλάσεις εικονικής βάσης. Το C++20 προσθέτει καθορισμένους αρχικοποιητές, επιτρέποντάς σας να ονομάσετε ποια μέλη αρχικοποιείτε.
#include <iostream>
#include <string>
struct Config {
std::string host = "localhost";
int port = 8080;
bool use_tls = false;
int max_connections = 100;
};
int main() {
// Traditional aggregate initialization
Config c1{"example.com", 443, true, 200};
// C++20 designated initializers — much more readable
Config c2{
.host = "api.example.com",
.port = 443,
.use_tls = true
// .max_connections uses default value 100
};
std::cout << c2.host << ':' << c2.port << '\n';
std::cout << "TLS: " << std::boolalpha << c2.use_tls << '\n';
std::cout << "Max: " << c2.max_connections << '\n'; // 100
return 0;
}Ορίστε τα μέλη δεδομένων ιδιωτικά από προεπιλογή και εκθέστε μόνο ό,τι χρειάζεται μέσω μιας ελάχιστης δημόσιας διεπαφής. Εάν μια κλάση δεν έχει αμετάβλητο για διατήρηση (είναι απλώς μια δέσμη δεδομένων), χρησιμοποιήστε ένα struct με δημόσια μέλη. Μην προσθέτετε getters και setters για κάθε πεδίο — αυτό ακυρώνει τον σκοπό της ενθυλάκωσης. Αντίθετα, παρέχετε σημαντικές λειτουργίες όπωςdeposit()καιwithdraw()αντίset_balance().
Εάν μια συνάρτηση μέλους δεν τροποποιεί την κατάσταση του αντικειμένου, σημειώστε την ωςconst. Χωρίςconst, δεν μπορείτε να καλέσετε τη συνάρτηση σε ένα αντικείμενοconstή μέσω μιας αναφοράςconst— κάτι που συμβαίνει συνεχώς όταν διαβιβάζετε αντικείμενα από τοconst&. Έναconstπου λείπει σε ένα Accessor είναι μια κοινή πηγή σφαλμάτων μεταγλώττισης σε μεγαλύτερες βάσεις κωδικών.
- Το
structκαι τοclassδιαφέρουν μόνο στην προεπιλεγμένη πρόσβαση: τοstructείναι δημόσιο, τοclassείναι ιδιωτικό - Η ενθυλάκωση προστατεύει αμετάβλητα κλάσης — χρησιμοποιήστε δεδομένα
privateμε μια ουσιαστική δημόσια διεπαφή - Επισημάνετε τις μη μεταλλαγμένες συναρτήσεις μέλους
constώστε να λειτουργούν με αναφορέςconst - Χρησιμοποιήστε το
inline static(C++17) για στατικά μέλη που ορίζονται στις κεφαλίδες - Οι καθορισμένοι αρχικοποιητές C++20 καθιστούν την εκκίνηση συγκεντρωτικών αναγνώσιμων και αυτο-τεκμηριωμένων
- Το
friendθα πρέπει να χρησιμοποιείται με φειδώ — συνήθως για υπερφορτώσεις χειριστή που χρειάζονται ιδιωτική πρόσβαση
Κουίζ — Δοκιμάστε τις γνώσεις σας
(15 XP)1. Ποια είναι η ΜΟΝΗ διαφορά μεταξύ`struct`και`class`στο C++;
2. Γιατί πρέπει να επισημάνετε τις λειτουργίες μέλους πρόσβασης ως`const`;
3. Τι επιτυγχάνει το`inline static int count_ = 0;`στο C++17;