Qual è la differenza tra una class concreta e una class astratta?

Sto imparando il C ++, ma sono confuso riguardo alla class astratta e alla class concreta. Alcuni esempi del mondo reale sarebbero apprezzati.

Una class astratta è una class per la quale uno o più metodi sono dichiarati ma non definiti, il che significa che il compilatore sa che questi metodi fanno parte della class, ma non quale codice da eseguire per quel metodo. Questi sono chiamati metodi astratti. Ecco un esempio di una class astratta.

class shape { public: virtual void draw() = 0; }; 

Questo dichiara una class astratta che specifica che qualsiasi discendente della class dovrebbe implementare il metodo draw se la class deve essere concreta. Non è ansible creare un’istanza di questa class perché è astratta, dopotutto, il compilatore non saprebbe quale codice eseguire se si è chiamato membro draw. Quindi non puoi fare quanto segue:

 shape my_shape(); my_shape.draw(); 

Per essere in grado di utilizzare effettivamente il metodo draw è necessario ricavare classi da questa class astratta, che implementano il metodo draw, rendendo concrete le classi:

 class circle : public shape { public: circle(int x, int y, int radius) { /* set up the circle */ } virtual draw() { /* do stuff to draw the circle */ } }; class rectangle : public shape { public: rectangle(int min_x, int min_y, int max_x, int max_y) { /* set up rectangle */ } virtual draw() { /* do stuff to draw the rectangle */ } }; 

Ora puoi istanziare il cerchio e il rettangolo degli oggetti concreti e utilizzare i loro metodi di disegno:

 circle my_circle(40, 30, 10); rectangle my_rectangle(20, 10, 50, 15); my_circle.draw(); my_rectangle.draw(); 

Ora, naturalmente, la domanda è: perché vorresti farlo? Non avresti potuto definire le classi di cerchio e rettangolo e aver eliminato l’intera class di forma? Potresti, ma allora non saresti in grado di sfruttare la loro eredità:

 std::vector my_scene; my_scene.push_back(new circle(40, 30, 10)); my_scene.push_back(new rectangle(20, 10, 50, 15)); std::for_each(my_scene.begin(), my_scene.end(), std::mem_fun_ref(&shape::draw) 

Questo codice consente di raccogliere tutte le forms in un unico contenitore. Questo lo rende molto più semplice se hai molte forms e molte forms diverse nella tua scena. Ad esempio ora possiamo disegnare tutte le forms in un colpo solo, e il codice che lo fa non ha nemmeno bisogno di conoscere i diversi tipi di forms che abbiamo.

Ora finalmente abbiamo bisogno di sapere perché la funzione di disegno della forma è astratta, e non solo una funzione vuota, cioè perché non abbiamo appena definito:

 class shape { public: virtual void draw() { /* do nothing */ } }; 

La ragione di ciò è che non desideriamo veramente oggetti di tipo shape, non sarebbero comunque cose reali, sarebbero astratti. Quindi non ha senso definire un’implementazione per il metodo draw, anche se vuoto. Rendere l’abstract della class di forma ci impedisce di istanziare erroneamente la class di forma, o di chiamare erroneamente la funzione di disegno vuota della class base invece della funzione di disegno delle classi derivate. In effetti definiamo un’interfaccia per qualsiasi class che vorrebbe comportarsi come una forma, diciamo che qualsiasi class dovrebbe avere un metodo di disegno che assomiglia a quello che abbiamo specificato dovrebbe.

Per rispondere alla tua ultima domanda, non esiste una “class derivata normale” ogni class è astratta o concreta. Una class che ha dei metodi astratti è astratta, qualsiasi class che non sia concreta. È solo un modo per differenziare i due tipi di classi. Una class base può essere astratta o concreta e una class derivata può essere astratta o concreta:

 class abstract_base { public: virtual void abstract_method1() = 0; virtual void abstract_method2() = 0; }; class concrete_base { public: void concrete_method1() { /* do something */ } }; class abstract_derived1 : public abstract_base { public: virtual void abstract_method3() = 0; }; class abstract_derived2 : public concrete_base { public: virtual void abstract_method3() = 0; }; class abstract_derived3 : public abstract_base { public: virtual abstract_method1() { /* do something */ } /* note that we do not provide an implementation for abstract_method2 so the class is still abstract */ }; class concrete_derived1 : public concrete_base { public: void concrete_method2() { /* do something */ } }; class concrete_derived2 : public abstract_base { public: virtual void abstract_method1() { /* do something */ } virtual void abstract_method2() { /* do something */ } /* This class is now concrete because no abstract methods remain */ }; 

La class astratta non può essere utilizzata per creare un object. Mentre la class concreta può essere utilizzata per creare un object.

Concreto significa ” esistere nella realtà o nell’esperienza reale; percepibile dai sensi; vero”. Considerando che l’ astratto significa ” non applicato o pratico; teorico ‘.

Una class astratta non può essere istanziata. Considerando che uno concreto può.

Una class astratta è una che ha una o più funzioni pure virtuali. Mentre una class concreta non ha funzioni virtuali pure.

Una class concreta è una class che può essere utilizzata per creare un object. Una class astratta non può essere utilizzata per creare un object (è necessario estendere una class astratta e creare una class concreta per poter creare un object).

Fai finta che ci sia una macchina in grado di “stampare” le materie prime e fare una macchina. Lo stampatore è una class concreta. Da questo possiamo creare oggetti per auto. Una class astratta sarebbe i progetti per lo stampatore. Non è ansible creare auto dai progetti della matrice, è necessario rendere la class di matrice prima dai progetti.

Una class astratta non può essere istanziata mentre è concreta. Una class astratta funge da “progetto” per le classi derivate, che possono essere istanziate.

Per esempio la class Car (abstract) mentre la class Audi S4 (derivante dalla Car ) è un’implementazione concreta.

Molto di questo ha riguardato queste altre domande:

  1. Cos’è una class astratta?
  2. Classi astratte vs interfacce
  3. Che cos’è un tipo di dati astratto nella programmazione orientata agli oggetti?
  4. File di intestazione separati per classi concrete – C ++

Un buon esempio di utilizzo di una class astratta è quando stai costruendo qualcosa di molto modulare. Supponiamo che tu stia lavorando con un archivio dati, ma che i dati potrebbero trovarsi in un database MySQL, database SQLite, file XML o testo normale. Per mantenere questa versatilità nel codice, è ansible creare una class AbstractDatastore che definisce i metodi pubblici che si desidera utilizzare per ottenere informazioni dal datastore. Quindi crei le tue implementazioni specifiche di AbstractDatastore , come XmlDatastore , SQLiteDatastore , ecc. Quindi, il tuo programma ha solo bisogno di sapere che sta ottenendo un AbstractDatastore e che deve avere quelle funzioni definite in AbstractDatastore ma non sa o interessa come i dati è memorizzato o recuperato.

Classe base e class derivata sono un concetto ortogonale per astrarre class contro class concreta.

Una class base è una class che non eredita da un’altra class. Una class derivata eredita da un’altra class.

Una class astratta è una che ha una o più funzioni pure virtuali. Una class concreta non ha virtual virtuali.

Una class astratta può essere una class base o una class derivata (è derivata da un’altra class astratta). Una class concreta può anche essere base o derivata. È anche ansible derivare una class astratta da una class concreta, aggiungendo una funzione virtuale pura alla class derivata. Ma in generale, c’è una class astratta di base e una o più classi derivate dal calcestruzzo.

C ++ Faq Lite è un sito eccellente per cercare risposte su questo tipo di domande.

A livello di progettazione, una class base astratta (ABC) corrisponde a un concetto astratto. Se chiedeste ad un meccanico se riparasse veicoli, probabilmente si chiederà quale tipo di veicolo aveste in mente. È probabile che non ripari navicelle spaziali, transatlantici, biciclette o sottomarini nucleari. Il problema è che il termine “veicolo” è un concetto astratto (ad esempio, non è ansible build un “veicolo” a meno che non si sappia quale tipo di veicolo build). In C ++, la class Vehicle sarebbe un ABC, con Bicycle, SpaceShuttle, ecc., Essendo classi derivate (un OceanLiner è un tipo di veicolo). Nel mondo reale OO, gli ABC si presentano dappertutto

Una class astratta è una class che ha una o più funzioni di membri virtuali puri. Non è ansible creare un object (istanza) di una class astratta

  class Shape { public: virtual void draw() const = 0; // = 0 means it is "pure virtual" ... }; 

La class concreta ha implementato tutto il suo metodo. Classe astratta tutto il suo metodo tranne alcuni (almeno uno) metodi non implementati in modo da poterlo estendere e implementare il metodo non implementato.

Vantaggio: estendendo dalla class astratta ottieni tutte le funzionalità della class base e sarai “forzato” ad implementare il metodo non implementato. Quindi il progettista della class ti sta costringendo a scrivere codice nel metodo astratto prima che la class ti sia di qualche utilità.