C ++ Notizen (acht) Objekte und Klassen neu lernen


Die wichtigsten OOP-Funktionen:

  • abstrakt
  • Kapselung und Verstecken von Daten
  • Polymorphismus
  • erben
  • Wiederverwendbarkeit des Codes

Um diese Funktionen zu implementieren und zu kombinieren, besteht die wichtigste Verbesserung von C ++ darin, Klassen bereitzustellen. Die meisten vorherigen Artikel befassten sich mit prozessorientierter Programmierung. Jetzt werden wir die objektorientierte Programmierung offiziell einführen.

1. Abstraktion und Klasse

1.1 Klassen in C ++

Verwenden Sie das Schlüsselwort class, um das Klassendesign anzugeben, und der Typname kann hier nicht verwendet werden. Die Klassenspezifikation besteht aus zwei Teilen:

Klassendeklaration: Beschreiben Sie den Datenteil in Form von Datenelementen und beschreiben Sie die öffentliche Schnittstelle in Form von Elementfunktionen (Methoden).
Klassenmethodendefinition: Beschreiben, wie Klassenelementfunktionen implementiert werden

Einfach ausgedrückt, die Klassendeklaration liefert den Entwurf der Klasse, und die Methodendefinition liefert die Details. In einer Klasse können Elementfunktionen in der Klasse definiert oder durch Prototypen dargestellt werden .

(1) Zugangskontrolle

Die Schlüsselwörter privat und öffentlich beschreiben die Zugriffssteuerung für Klassenmitglieder. Klassenobjekte können direkt auf öffentliche Teile zugreifen, jedoch nur über öffentliche Mitgliederfunktionen (oder Freundfunktionen) auf private Mitglieder von Objekten. C ++ bietet auch das geschützte Schlüsselwort, das in die Klassenvererbung eingeführt wird.

Das Ausblenden von Daten verhindert nicht nur den direkten Zugriff auf die Daten, sondern befreit Entwickler (Klassenbenutzer) auch davon, zu wissen, wie die Daten dargestellt werden.

(2) Kontrolle des Zugangs zu Mitgliedern: öffentlich oder privat

Das Ausblenden von Daten ist eines der Hauptziele von OOP. Daher werden Datenelemente normalerweise im privaten Mitgliedsteil und die Elementfunktionen, aus denen die Klassenschnittstelle besteht, im öffentlichen Teil platziert . Natürlich können Sie Elementfunktionen auch in den privaten Teil einfügen, sodass Sie sie nur über öffentliche Methoden aufrufen und private Elementfunktionen nicht direkt aus dem Programm aufrufen können.

Das private in der Klassendeklaration kann weggelassen werden, da dies die Standardzugriffskontrollmethode für die Klasse ist.

class World
{
    
    
	float mass;
publicvoid tellall(void);
}

Um das Konzept des Versteckens von Daten hervorzuheben, verwenden wir hier ausdrücklich private.

(3) Klasse und Struktur

Die Klassenbeschreibung ähnelt stark einer Strukturdeklaration (alle haben Mitgliedsfunktionen, öffentliche und private Tags). Tatsächlich erweitert C ++ die Struktur, um dieselben Eigenschaften wie die Klasse zu haben. Der Standardzugriffstyp der Struktur ist öffentlich und die Klasse ist privat.

C ++ - Programmierer verwenden normalerweise Klassen, um Klassenbeschreibungen zu implementieren und die Struktur auf reine Datenobjekte zu beschränken.

1.2 Implementieren Sie Klassenelementfunktionen

(1) Die Definition der Mitgliedsfunktion

Mitgliedsfunktionen sind regulären Funktionen sehr ähnlich, weisen jedoch zwei besondere Merkmale auf.

  • Verwenden Sie beim Definieren einer Klassenelementfunktion den Parsing-Operator (: :), um die Klasse zu identifizieren, zu der die Funktion gehört.
  • Klassenmethoden können auf private Komponenten der Klasse zugreifen.

Klassendefinition:

void Stock::update(double price)
{
    
    ...}

(2) Inline-Methode

Die Definition der Elementfunktion Die Funktion in der Klassendeklaration wird automatisch zu einer Inline-Funktion . Klassendeklarationen verwenden häufig kleine Elementfunktionen als Inline-Funktionen.

Wenn Sie möchten, können Sie Elementfunktionen außerhalb der Klassendeklaration definieren und sie zu Inline-Funktionen machen. Verwenden Sie einfach das Inline-Qualifikationsmerkmal, wenn Sie die Funktion im Abschnitt zur Klassenimplementierung definieren:

inline void Stock::set_tot()
{
    
    ...}

Die speziellen Regeln für Inline-Funktionen erfordern, dass sie in jeder Datei definiert werden, in der sie verwendet werden. Daher fügen wir Inline-Definitionen normalerweise in die Header-Datei der Definitionsklasse ein.

2. Klassenkonstruktor und Destruktor

Eines der Ziele von C ++ ist es, die Verwendung von Klassenobjekten mit der Verwendung von Standardtypen identisch zu machen. Um die Klassenobjekte wie den int-Typ zu initialisieren, müssen wir auf private Mitglieder zugreifen. Daher müssen wir geeignete Elementfunktionen für entwerfen Konvertieren Sie die Objektinitialisierung erfolgreich. Aus diesem Grund bietet C ++ einen speziellen Konstruktor für Elementfunktionsklassen, der speziell zum Erstellen neuer Objekte verwendet wird.

2.1 Deklarieren und definieren Sie den Konstruktor

Der Prototyp des Konstruktors lautet wie folgt: Der folgende Prototyp verwendet Standardparameter.

Stock(const string& co, long n = 0, double pr = 0.0);

Es ist wie folgt definiert:

Stock::Stock(const string& co, long  n, double pr)
{
    
    
	company = co;//赋值给私有数据成员
	...
}

Um private Datenelemente von anderen Variablen zu unterscheiden, werden häufig Unterstriche hinzugefügt, z. B. company_.

2.2 Verwenden des Konstruktors

  • Aufrufkonstruktor anzeigen
Stock food = Stock("world cabbage", 250, 1.25);
  • Einsiedler ruft den Konstruktor an
Stock garment("Furry Mason", 50, 2.5);

Jedes Mal, wenn Sie ein Klassenobjekt erstellen (sogar mithilfe von new dynamisch Speicher zuweisen), verwendet C ++ den Klassenkonstruktor.

Stock * pstock = new Stock("Electroshock", 18, 19.0);

Das oben erstellte Objekt hat keinen Namen, aber die Adresse des erstellten Objekts wird pstock zugewiesen.

  • C ++ - Listeninitialisierung
Stock hot_tip = {
    
    "Derivatives", 100, 45};
Stock jock {
    
    "Sport Age Storage"};
Stock temp {
    
      };

2.3 Standardkonstruktor

Wenn kein Anfangswert angegeben wird, wird der Standardkonstruktor aufgerufen. Z.B:

Stock fluffy_the_cat;//使用默认构造函数

Wenn in der Klasse kein Konstruktor angegeben ist, stellt C ++ automatisch einen Standardkonstruktor bereit und führt keine Arbeit aus:

Stock::Stock( ) {
    
     };

Es ist anzumerken, dass der Compiler genau dann einen Standardkonstruktor bereitstellt, wenn kein Konstruktor definiert ist. Wenn die Klasse einen Konstruktor definiert, muss der Benutzer einen Standardkonstruktor dafür bereitstellen. Wenn ein nicht standardmäßiger Konstruktor bereitgestellt wird, aber kein standardmäßiger Konstruktor bereitgestellt wird, ist die folgende Deklaration falsch.

Stock stock1;//没有默认构造函数,报错!!!

Beachten Sie den Unterschied zwischen den folgenden Definitionen:

Stock first("Concrete");//隐式构造函数调用,非默认构造函数调用
Stock second();//定义一个函数,它的返回值为Stock类型
Stock third;//隐式地调用默认构造函数。

2.4 Destruktor

Wenn das Objekt abläuft, ruft das Programm automatisch einen speziellen Elementfunktionszerstörer auf. Der Destruktor schließt die Bereinigungsarbeit ab, was eigentlich sehr nützlich ist. Um beispielsweise den durch new zugewiesenen Speicher zu bereinigen, muss die Definition des Destruktors nur ~ vor dem Klassennamen hinzufügen, sodass der Destruktor von Stock ~ Stock () ist. .

Da der Destruktor keine wichtigen Arbeiten ausführt, kann er als eine Funktion geschrieben werden, die nichts tut:

Stock::~Stock()
{
    
    ...}
  • Wenn Sie ein statisches Speicherklassenobjekt erstellen, wird dessen Destruktor am Ende des Programms automatisch aufgerufen.
  • Wenn Sie ein automatisches Speicherklassenobjekt erstellen, wird dessen Destruktor automatisch aufgerufen, wenn das Programm die Ausführung des Codeblocks beendet hat.
  • Wenn das Objekt von new erstellt wird, befindet es sich im freien Speicherbereich, und wenn delete zum Freigeben des Speichers verwendet wird, wird sein Destruktor automatisch aufgerufen.

Der Destruktor ist erforderlich. Wenn der Programmierer keinen Destruktor bereitstellt, deklariert der Compiler hermitisch einen Standarddestruktor.

2.5 const Mitgliedsfunktion

Wenn Sie ein const-Objekt definieren, kann es keine eigene Funktion aufrufen. Z.B:

const Stock land = Stock("kludgehorn");
land.show();//不被允许,因为不能确保调用的对象不被修改!!!

Die Lösung besteht darin, const nach der Elementfunktionsdeklaration und der Elementfunktionsdefinition hinzuzufügen, um sicherzustellen, dass die Funktion das aufrufende Objekt nicht ändert (das Land nicht ändert) :

void show() const;//成员函数原型
void Stock::show() const//成员函数定义
{
    
    
	...
}

Auf diese Weise definierte Elementfunktionen werden als konstante Elementfunktionen bezeichnet.

3. dieser Zeiger

Wenn eine Methode auf zwei Objekte ausgelegt ist, muss manchmal der Zeiger this in C ++ verwendet werden. Wenn wir beispielsweise die Werte zweier Objekte vergleichen möchten, können wir sie wie den folgenden Aufruf aufrufen, unabhängig davon, welches verwendet wird.

top = stock1.topval(stock2);//显示调用stock2,隐式调用stock1
top = stock2.topval(stock1);//显示调用stock1,隐式调用stock2

Spezifisches Code-Definitionsfragment:

const Stock& Stock::topval(const Stock& s) const
{
    
    
	if(s.total_val > total_val)
		return s;//返回被调用的对象
	else
		return *this;//返回自己的对象本身,this是本身的地址
}

Beachten Sie die folgenden Punkte im obigen Codefragment:

  • s gibt an, dass explizit auf das Objekt zugegriffen wird und implizit auf das Objekt zugegriffen wird, das topval aufruft.
  • Die Konstante in den Klammern bedeutet, dass das Objekt, auf das explizit zugegriffen wird, nicht geändert wird, und die Konstante nach den Klammern bedeutet, dass das Objekt, auf das implizit zugegriffen wird, nicht geändert wird.
  • Dies ist die Adresse des Objekts, auf das implizit zugegriffen wird, und * dies repräsentiert das Objekt.

4. Objektarray

Wir können mehrere Objekte in einem Array von Objekten erstellen. Im Folgenden werden 4 Objekte erstellt, von denen jedes den Standardkonstruktor aufruft.

Stock mystuff[4];//创建4个对象

Wir können verwenden, um auf Datenelemente und Elementfunktionen zuzugreifen:

mystuff[0].update();
mystuff[0].show();

Wenn wir den Standardkonstruktor nicht verwenden möchten, können wir den Konstruktortyp selbst auswählen.

const int STKS = 4;
Stock stocks[STKS] = {
    
    
	Stock("Nano", 12.5, 20),
	Stock();
	Stock("Mono", 130, 3.25),
	};

Aktien [0] und Aktien [2] verwenden denselben Konstruktor, Aktien [1] verwenden den Standardkonstruktor, Aktien [3] führen keine Anzeigeinitialisierung durch und rufen auch den Standardkonstruktor auf.

5. Klassenumfang

Der Bereich des in der Klasse definierten Namens (z. B. der Name des Klassendatenelements und der Name der Klassenelementfunktion) ist die gesamte Klasse, und der Bereich ist, dass der Name der gesamten Klasse nur in der Klasse bekannt ist , aber nicht außerhalb der Klasse.

Wenn Sie Mitglieder außerhalb einer Klasse verwenden, müssen Sie je nach Kontext den Operator für direkte Mitglieder (.), Den Operator für indirekte Mitglieder (->) oder den Operator für die Bereichsauflösung (: :) verwenden.

5.1 Konstanten, deren Gültigkeitsbereich eine Klasse ist

Wenn der Literalwert der Klassendeklaration für alle Objekte gleich ist, können wir die Klasse verwenden, um darauf zuzugreifen. Die folgende Operation ist jedoch falsch, da bei der Definition der Klasse kein Speicherplatz zugewiesen wird .

class Bakery
{
    
    
	private:
		const int Months = 12;//不可以
		double consts[Months];

Wir haben zwei Möglichkeiten, um die oben genannten Operationen zu erreichen:

(1) Aufzählung

class Bakery
{
    
    
	private:
		enum{
    
    Months = 12};
		double consts[Months];

Wenn Sie Aufzählungen auf diese Weise deklarieren, werden keine Klassendatenelemente erstellt. Mit anderen Worten, alle Objekte enthalten keine Aufzählungen. Außerdem ist Months nur ein symbolischer Name. Wenn er im Code der gesamten Klasse gefunden wird, ersetzt der Compiler ihn durch 30.

(2) statisch

class Bakery
{
    
    
	private:
		static const int Months = 12;
		double consts[Months];

Dadurch wird eine Konstante namens Monate erstellt, die mit anderen statischen Variablen anstatt im Objekt gespeichert wird. Daher gibt es nur einen Monat konstant, was wird geteilt durch die Bäckerei Objekt . In C ++ 98 kann diese Technik nur zum Deklarieren statischer Konstanten mit Werten und Ganzzahlen oder Aufzählungen verwendet werden, es können jedoch keine Doppelkonstanten gespeichert werden. C ++ 11 beseitigt diese Einschränkung.

Beachten Sie, dass die Initialisierung in der Klasse nur statische Daten sein kann. Elemente sind integrale oder vom Typ const aufgezählte. Andere Typen müssen in der CPP-Datei initialisiert werden, die die Klasse definiert.

5.2 Aufzählung im Geltungsbereich (C ++)

Es gibt einige Probleme mit herkömmlichen Aufzählungen. Beispielsweise treten bei den folgenden Aufzählungen Konflikte auf.

enum egg {
    
    Small, Medium, Large, Jumbo };
enum t_shirt {
    
    Small, Medium, Large, Xlarge};

Der obige Code kann nicht kompiliert werden, da Ei und t_shirt dieselbe Aufzählung haben und Konflikte auftreten. Um dieses Problem zu lösen, bietet C ++ 11 eine neue Aufzählung, deren Gültigkeitsbereich eine Klasse ist.

enum class egg {
    
    Small, Medium, Large, Jumbo };
enum class t_shirt {
    
    Small, Medium, Large, Xlarge};

Sie können auch struct anstelle von class verwenden, unabhängig davon, welche Methode Sie verwenden. Sie müssen den Aufzählungsnamen verwenden, um die Aufzählung einzuschränken.

egg choice = egg::Large;
t_shirt Floyd = t_shirt::Large;

C ++ 11 verbessert auch die Typensicherheit von In-Scope-Aufzählungen, die nicht implizit in Ganzzahlen konvertiert werden können.

enum egg {
    
    Small, Medium, Large, Jumbo };//普通类型
enum class t_shirt {
    
    Small, Medium, Large, Xlarge};//类作用域
egg one = Medium;
t_shirt rolf = t_shirt::Large;
int king = one;//可以,普通类型转换
int ring = rolf;//不可以,不能进行作用域的转换
if(king < Jumbo)//可以
if(king < t_shirt::Medium)//不可以,不能隐士转换为int比较

Aber wir können explizit konvertieren:

int Frodo = int(t_shirt::Small);

Standardmäßig ist die zugrunde liegende Implementierung der Aufzählung int, aber in C ++ 11 können wir die zugrunde liegende Implementierung eines bestimmten Typs explizit verwenden, und der zugrunde liegende Typ muss eine Ganzzahl sein.

enum class : short t_shirt {
    
    Small, Medium, Large, Xlarge};//底层类型指定为short

6. Abstrakte Datentypen

Abstrakter Datentyp (abstrakter Datentyp, ADT) unter Verwendung von Klassen zur Darstellung allgemeiner Konzepte. Klassen eignen sich sehr gut zur Darstellung von ADT, Funktionsschnittstellen für öffentliche Mitglieder bieten Dienste, die von ADT beschrieben werden, und private Teile von Klassen und Klassenmethodencodes bieten Implementierungen , die vor Kunden der Klasse verborgen sind.


Übersicht Katalog
Zurück: (7) Speichermodell und Namespace
Weiter: (8) Klasse verwenden


Artikelreferenz: "C ++ Primer Plus Sixth Edition"

Ich denke du magst

Origin blog.csdn.net/QLeelq/article/details/111059334
Empfohlen
Rangfolge