PDA

View Full Version : [C++] Classe astratta senza funzioni virtuali pure!


Ikon O'Cluster
25-09-2009, 16:06
Supponiamo il seguente esempio:


class ClasseAstratta {
protected:
int qualcosa;

public:

ClasseAstratta() {
// qualcosa...
}

void qualcosaDaFare() {
// qualcosa...
}
};


Non è astratta perchè va definita necessariamente una funzione virtuale pura, contrariamente al JAVA... Tuttavia se per classe astratta si considera la sua sola caratteristica di non istanziabilità allora questa definizione:


class ClasseAstratta {
protected:
int qualcosa;

ClasseAstratta() {
// qualcosa...
}

public:

void qualcosaDaFare() {
// qualcosa...
}
};


La reputate valida? L'assenza di costruttori pubblici è possibile al fine di evitare l'istanziazione?

fero86
25-09-2009, 19:52
L'assenza di costruttori pubblici è possibile al fine di evitare l'istanziazione? no:

class ClasseNonAstratta :
public ClasseAstratta
{
public:
ClasseNonAstratta() {}
};

ClasseAstratta ca = ClasseNonAstratta();


edit - o meglio, sarebbe possibile se tu i costruttori pubblici li avessi levati proprio tutti, ma hai lasciato il costruttore di copia.

Ikon O'Cluster
25-09-2009, 20:16
Quindi come dovrei fare?

class ClasseAstratta {
protected:
int qualcosa;

ClasseAstratta() {
// qualcosa...
}

ClasseAstratta(const ClasseAstratta&) {
// qualcosa...
}

public:

void qualcosaDaFare() {
// qualcosa...
}

Così???

fero86
25-09-2009, 20:52
si, a quel punto dovrebbe andare bene se non sto dimenticando qualcosa, solo che non credo che alcuno definirebbe quella una classe astratta.

Tommo
25-09-2009, 21:08
Non vorrei essere di troppo, ma


class ClasseAstratta abstract {
protected:
int qualcosa;

public:

ClasseAstratta() {
// qualcosa...
}

void qualcosaDaFare() {
// qualcosa...
}
};


E' sintassi valida C++ che produce una classe astratta. Almeno a me funziona :asd:

Ikon O'Cluster
25-09-2009, 21:24
Non vorrei essere di troppo, ma


class ClasseAstratta abstract {
protected:
int qualcosa;

public:

ClasseAstratta() {
// qualcosa...
}

void qualcosaDaFare() {
// qualcosa...
}
};


E' sintassi valida C++ che produce una classe astratta. Almeno a me funziona :asd:

davvero???????????????????????????????

tomminno
25-09-2009, 22:59
Non vorrei essere di troppo, ma


class ClasseAstratta abstract {
protected:
int qualcosa;

public:

ClasseAstratta() {
// qualcosa...
}

void qualcosaDaFare() {
// qualcosa...
}
};


E' sintassi valida C++ che produce una classe astratta. Almeno a me funziona :asd:

Ehm direi che abstract non rientra tra le keyword del C++.
E' invece un'estensione del C++/CLI.
Stai usando Visual Studio vero? :D

Ikon O'Cluster
25-09-2009, 23:04
Ehm direi che abstract non rientra tra le keyword del C++.
E' invece un'estensione del C++/CLI.
Stai usando Visual Studio vero? :D

Mi sembrava strano :D e se non ho funzioni da rendere virtuali pure come faccio a generare una classe astratta?

Tommo
26-09-2009, 01:28
Doh lo sospettavo in effetti, non ero riuscito a trovare riscontro su Google :asd:

Comunque nel progetto dove l'ho provato non è abilitata alcuna estensione MS, l'ho fatto da 0... boh!

Cmq credo che questo sia in realtà un non-problema: cose come abstract imo servono per permettere una visione intuitiva dell'uso del software... quindi fare una roba come nascondere i costruttori riuscirebbe più sviante che altro.
Suggerirei di permetterne la creazione, ma dargli un nome molto esplicativo, tipo MiaClasseAstratta... e di spiegare bene il tutto nella documentazione (la quale è parte del programma quanto il codice).
Eppoi, se la classe PUO' implementare tutti i suoi metodi, che ha di astratto? :asd:

gugoXX
26-09-2009, 08:45
Per aggiungere un po' al discorso, una classe non astratta con tutti i costruttori protetti e' la modalita' standard per creare il pattern Singletone, quando vuoi essere sicuro che ci sia una ed una sola istanza della classe ovunque per l'applicazione
Ovvero puoi sempre costruire un oggetto di tale classe, ma ovviamente all'interno della classe stessa, ed al SingleTone e' proprio quello che serve.


public class Prova
{
protected void Prova()
{
// Fai eventualmente qualcosa
}

private static Prova MyUniqueInstance;
public static Prova GetSingleTone()
{
if (MyUinqueInstance==null)
MyUniqueInstance = new Prova();
return MyUinqueInstance;
}
}

....

//Da usarsi poi cosi'
...
Prova myProva = Prova.GetSingleTone();


Eventualmente condito da regioni critiche per ambienti multithread.

Ikon O'Cluster
26-09-2009, 12:03
Per aggiungere un po' al discorso, una classe non astratta con tutti i costruttori protetti e' la modalita' standard per creare il pattern Singletone, quando vuoi essere sicuro che ci sia una ed una sola istanza della classe ovunque per l'applicazione
Ovvero puoi sempre costruire un oggetto di tale classe, ma ovviamente all'interno della classe stessa, ed al SingleTone e' proprio quello che serve.


public class Prova
{
protected void Prova()
{
// Fai eventualmente qualcosa
}

private static Prova MyUniqueInstance;
public static Prova GetSingleTone()
{
if (MyUinqueInstance==null)
MyUniqueInstance = new Prova();
return MyUinqueInstance;
}
}

....

//Da usarsi poi cosi'
...
Prova myProva = Prova.GetSingleTone();


Eventualmente condito da regioni critiche per ambienti multithread.

Tuttavia l'assenza di getSingleTone permette di evitare anche quell'unica istanza. Di fatto in questo modo la classe è astratta se si considera astratta "una classe non istanziabile" alla maniera di JAVA. Per il C++ tuttavia la definizione non è rigorosa perchè vi è l'assenza di funzioni virtuali pure.

Spiego il mio problema. Ho una classe base che definisce dei metodi. Ho due sottoclassi che derivano da essa che aggiungono funzionalità. Tuttavia la classe base costituisce solo un raggruppamento delle caratteristiche comuni e non esiste nella realtà del sistema di interesse. E' utile però raggruppare le funzioni comuni ma è tuttavia errato e dannoso poter istanziare oggetti della classe base. D'altro canto non posso rendere astratta la classe perchè le caratteristiche comuni non hanno necessità di essere ridefiniti dalle sottoclassi e non esistono caratteristiche comuni per le quali sia possibile avere funzioni virtuali pure, a meno di non darne la medesima definizione in entrambe le sottoclassi. In tal senso la classe base deve essere astratta nel senso inteso in Java, ma sto lavorando in C++. Quindi un SingleTone carente della funzione membro che genera l'unica istanza della classe si tradurrebbe in un fantomatico "NullTone" che coinciderebbe con il mio scopo. Ma la domanda che vi ho posto non era volta a trovare un "pezzotto" era rivolta a trovare la soluzione più elegante, leggibile e soprattutto che evitasse a terzi di commettere azioni "illegali" rispetto alle regole del sistema reale che ho modellato!

gugoXX
26-09-2009, 13:02
Ma non puoi mettere anche una funzione virtuale pura inutile in classe base, oltre che le funzioni reali?
Se questo e' il modo sufficiente per evitare che il compilatore crei un'istanza della classe base hai raggiunto lo scopo.

Tommo
26-09-2009, 13:04
Beh imo a sto punto c'è solo la "pezza"... oppure potresti spiegarlo bene altrove ma lasciare la classe non astratta. o magari tutte e due.

Cmq il nome è Singleton (http://en.wikipedia.org/wiki/Singleton_pattern) non SingleTone (http://www.google.it/search?rlz=1C1GGLS_itIT326IT326&sourceid=chrome&ie=UTF-8&q=singletone) :D

Ikon O'Cluster
26-09-2009, 13:29
Beh imo a sto punto c'è solo la "pezza"... oppure potresti spiegarlo bene altrove ma lasciare la classe non astratta. o magari tutte e due.

Cmq il nome è Singleton (http://en.wikipedia.org/wiki/Singleton_pattern) non SingleTone (http://www.google.it/search?rlz=1C1GGLS_itIT326IT326&sourceid=chrome&ie=UTF-8&q=singletone) :D

Si è vero ho controllato il nome su "Design patterns" (Gamma) ed è Singleton... cmq al di là di questo inserire qualcosa tipo:

//! Do nothing: only to abstract the class...
virtual void pureVirtual() = 0;

Mi sembra a dir poco una oscenità!!! :D A quel punto nascondo i costruttori e ci scrivo che l'ho fatto per evitare l'istanziazione!!!