Quando entrano in uso le "funzioni statiche"?


25

OK, ho imparato cos'è una funzione statica, ma ancora non vedo perché siano più utili delle funzioni dei membri privati. Questa potrebbe essere una specie di domanda newb-ish qui, ma perché non sostituire semplicemente tutte le funzioni di membri privati ​​con funzioni statiche?


1
Non dovrebbe essere "sostituire tutte le funzioni statiche con funzioni di membri privati"? Attualmente, stai affermando che non vedi il punto dei metodi statici e continua chiedendoti perché non ne usiamo più.

5
Che cos'è una "funzione statica"? In C ++, ci sono almeno due significati (e per ultimo ho visto le bozze di C ++ 11, avevano rimosso l'avviso di deprecazione staticper limitare le funzioni all'ambito dei file.
David Thornley,

Intendi "funzione statica" nel senso di funzione libera statica dell'ambito di file in C / C ++, o come "funzione / metodo di memoria statica"? È un'enorme differenza!
Jan Hudec,

@JanHudec: Penso che data la presenza di private memberpossiamo tranquillamente presumere che l'OP stia chiedendo il concetto di OO e non ha idea di statica dell'ambito dei file.
Matthieu M.

@MatthieuM .: In realtà la presenza di "membro privato" è esattamente ciò che mi porta a credere che significhi funzioni statiche in senso C ++. Poiché le funzioni statiche con ambito file e le funzioni membro privato sono le due cose che hanno un uso molto simile in C ++, mentre la sostituzione di un membro statico pubblico con un membro non statico privato non ha molto senso. Sfortunatamente l'OP non sembra rispondere.
Jan Hudec,

Risposte:


25

Supponendo che tu stia utilizzando OOP , usa le funzioni statiche quando non dipendono da alcun membro della classe. Possono ancora essere privati, ma in questo modo sono ottimizzati in quanto non dipendono da nessuna istanza dell'oggetto correlato.

Oltre a quanto sopra, trovo utili le funzioni statiche quando non si desidera creare un'istanza di un oggetto solo per eseguire una funzione pubblica su di esso. Questo è principalmente il caso delle classi di supporto che contengono funzioni pubbliche per svolgere un lavoro ripetitivo e generale, ma non è necessario mantenere alcuno stato tra le chiamate.


Grazie Bernard. A proposito, sai cosa significa per un compilatore "associare un metodo alla classe"?
Templare oscuro,

@ Dark Templar: non posso dire di si. È specifico per una lingua particolare?
Bernard,

Ho un leggero problema con la tua definizione "non dipendono da nessun membro della classe". Le funzioni statiche dei membri non possono accedere a nessun membro non statico, tuttavia possono accedere ai membri statici. I membri statici sono membri della classe.
nuova stampa il

@newprint: hai ragione, tuttavia non è quello che ho detto. Ho detto quando essi non dipendono da qualche membro della classe. L'uso dei membri statici va bene se sono necessari, ma potrebbe non essere sempre così.
Bernard,

8

Cercando una spiegazione più semplificata di quanto sopra (abbastanza buone).

Un oggetto è normalmente codice + dati. Un metodo statico viene utilizzato quando si ha a che fare solo con la parte "codice" (non vi sono dati / stati mantenuti (tranne i membri di dati statici)).


5

Perché non richiedono un'istanza e possono essere pubblici. Supponiamo che tu abbia bisogno di una funzione per ottenere il massimo comune denominatore (GCD; molto utile per le classi di frazione; e sì, questo è solo un semplice esempio). Non ha senso creare una classe di oggetti il ​​cui unico scopo è che puoi avere un thispuntatore che non ti serve né in cui utilizzare gcd. Quindi usi un metodo statico per questo, idealmente sulla classe che utilizza effettivamente il GCD (ad es. Nella classe delle frazioni).

Di sicuro se ci sono solo metodi statici, stai sbagliando OOP e dovresti passare a fare effettivamente OOP o usare un linguaggio più appropriato al tuo paradigma.


Non sarebbe meglio nel tuo esempio usare una funzione gratuita?
Ela782

2
@ Ela782 Se la lingua ha funzioni gratuite, sì.

Ok, grazie per la rassicurazione. Ho imparato questa best practice solo di recente. Tuttavia, al momento ho problemi a vedere quando una funzione pubblica statica membro potrebbe effettivamente essere utile, diciamo in un linguaggio come C ++. Il caso d'uso per entrambi è quando la funzione non dipende o necessita di un'istanza della classe, quindi le funzioni libere sono la raccomandazione. Forse questa dovrebbe essere una nuova domanda.
Ela782

1
@ Ela782 Sì, potrebbe fare una bella domanda. Due punti rapidi: in C ++, in particolare, i membri statici sono utili per la meta-programmazione dei modelli poiché è possibile passare un tipo come parametro modello ma non uno spazio dei nomi. In generale, le funzioni statiche possono essere utilizzate per indicare che la funzione appartiene davvero a una classe, invece di appartenere a uno spazio dei nomi (think stuff::Thing::Load(...)vs stuff::LoadThing()).

2

Li uso come funzioni di supporto per compiti comuni, ad esempio:

  • Conversione di gradi in radianti (e viceversa);
  • Hashing a string;
  • Convertendo da enum a qualcos'altro (in questo progetto sto lavorando, fungono da tabella hash);

La maggior parte dei miei file che raggruppano le funzioni statiche hanno il suffisso Helper, il che significa che è quello che fanno, mi aiutano ad andare da qualche parte più velocemente.


2

Quanto a un metodo statico è:

I metodi statici non richiedono un'istanza della classe né possono accedere implicitamente ai dati (o questo, io, io, ecc.) Di tale istanza. [ 1 ]

Esempi di quando sono utili metodi statici:

  • Metodi globali / di aiuto
  • Ottenere risultati di query da una classe del modello di dati (chiamando un SP)

Usali solo dove appropriato.

  1. Se ti ritrovi a copiare gli stessi metodi in più oggetti, considera di rendere il metodo statico in modo da poter seguire DRY.
  2. Usa metodi statici se non hai bisogno di un'istanza di un oggetto (non stai lavorando su e variabili d'istanza dell'oggetto)

Se molti dei tuoi dati sono al di fuori degli oggetti e vengono elaborati tramite metodi statici, il tuo codice non è orientato agli oggetti e potrebbe diventare difficile da mantenere.


1

Statico e privato sono in effetti ortogonali: un metodo può essere statico, o privato, o nessuno, o entrambi.

Statico vs. non statico (noto anche come "metodi di istanza") indica se il metodo opera sulla classe stessa (statica) o su un'istanza particolare (non statica). A seconda della lingua, puoi chiamare un metodo statico tramite un'istanza, ma non puoi mai accedere all'istanza tramite un metodo statico (il che implica anche che non puoi chiamare alcun metodo non statico dall'interno di un metodo statico, semplicemente perché non hai thisoggetto). Utilizzare metodi statici per implementare comportamenti concettualmente collegati alla classe, ma che non si "legano" a un'istanza specifica. Un altro scenario in cui potresti voler usare metodi statici è quando hai una funzione che opera su due istanze di una classe e nessuno degli operandi merita uno stato privilegiato - per esempio, supponendo che tu abbia una classeVectore si desidera implementare l'addizione; il tuo metodo di aggiunta potrebbe essere chiamato come a.Add(b), ma Vector.Add(a, b)probabilmente ha più senso.

Privato vs. pubblico riguarda la visibilità del metodo. I metodi privati ​​sono accessibili solo nell'ambito della classe, mentre i metodi pubblici sono accessibili da qualsiasi luogo. L'uso più importante per questo è l'incapsulamento: rendendo pubblici solo i metodi e le proprietà che sono assolutamente necessari al resto del codice per comunicare con la classe, si limitano i punti in cui il codice esterno può introdurre problemi e si evitano problemi all'interno la tua classe dal sanguinamento nel resto del progetto.

Quindi, regola empirica:

  • rendere private tutte le funzioni membro, tranne quelle che devono essere chiamate dall'esterno della classe
  • rendere tutti i metodi metodi di istanza, a meno che non abbiano senso anche quando non esiste alcuna istanza della classe

0

Uso metodi statici sia in C ++ che in C # per classi di utilità, classi che non hanno dati di istanza, solo un modo per raggruppare una raccolta di metodi utili e correlati.

int count1 = DBUtil::GetCountOfSlackerEmployees();
int count2 = DBUtil::GetCountOfEmployedSlackers();

0

Supponendo che tu stia parlando di C ++ (non hai detto) e di avere i termini giusti (cioè non intendi funzioni / metodi dei membri):

Anche una funzione di membro privato deve ancora essere dichiarata nell'intestazione, il che significa che diventa effettivamente parte dell'API e dell'ABI della classe, anche se l'utente non può effettivamente chiamarla. Se aggiungi, modifichi o elimini la funzione di membro privato, stai forzando la ricompilazione di tutte le classi dipendenti (l'intestazione è cambiata, non puoi conoscerla meglio) e quando lo fai in una libreria, devi considerare la compatibilità per l'applicazione usando esso.

D'altra parte, le funzioni statiche con ambito file non ottengono un simbolo pubblico, quindi è possibile aggiungerle, modificarle o eliminarle a piacere e nulla al di là di un'unità di compilazione sarà mai influenzato.


0

In genere è necessario un main statico che funga da punto di ingresso per il programma. Potrebbe essere un po 'importante.


0

Una funzione statica (e ci sono significati diversi per quel termine in diverse lingue), non richiede alcuno stato mantenuto tra le chiamate. Se è concettualmente strettamente legato a ciò che fa una classe, rendila una funzione di classe (come in una classe non un oggetto), oppure, in caso contrario, rendila una funzione globale (o a livello di modulo, qualunque cosa). Non appartiene a un oggetto se non ha bisogno dello stato dell'oggetto.

Se passi continuamente lo stato, non è proprio una funzione stateless, stai solo facendo una funzione stateful con sintassi stateless. In quel caso, probabilmente appartiene all'oggetto chiamante, o forse è indicato un refactoring per allineare meglio lo stato e il comportamento.


0

"perché non sostituire semplicemente tutte le funzioni di membri privati ​​con funzioni statiche?"

... perché un membro privato può accedere ai dati dell'istanza pur consentendo che avvenga solo dalle chiamate effettuate all'interno delle funzioni di altri membri. La funzione statica può essere privata, ma non sarà in grado di modificare o fare riferimento a un'istanza della classe a meno che l'istanza non venga passata come parametro.


0

È divertente come nessuno sia ancora stato in grado di dare una buona risposta. Non sono sicuro neanche questo. Probabilmente dovresti prenderlo come un suggerimento che dovrebbero essere usati il ​​meno possibile. Dopo tutto sono procedurali piuttosto che OOP.

Ecco alcuni altri esempi:

In Obj-C, dove vengono chiamati metodi di classe, vengono comunemente utilizzati come wrapper di allocazione in cui l'oggetto viene inserito nel pool di conteggio dei riferimenti prima di essere restituito.

Un altro esempio di Obj-C è la registrazione di una nuova classe in una raccolta di classi. Supponiamo che tu abbia una serie di classi ognuna delle quali gestisce un tipo di file. Quando si crea una nuova classe per un nuovo tipo di file, è possibile registrarla nella raccolta (una variabile globale) utilizzando un metodo statico nella classe che determina il tipo di file.

In C ++ un altro uso che mi viene in mente è quello di catturare dolcemente gli errori. La tua funzione di costruzione non può fallire, tranne lanciando un'eccezione. È possibile impostare una variabile di istanza di errore, ma non è sempre appropriato. Invece è possibile eseguire le parti che potrebbero non funzionare in un wrapper statico e quindi allocare e restituire il nuovo oggetto o NULL in caso di errore.


0

Diciamo che vuoi calcolare il seno di qualcosa.

Senza statico:

Math math = new Math()
double y = math.sin(x)

Con statico:

double y = Math.sin(x)

Non ha senso rendere sinnon statico. È apolide e elabora semplicemente l'input.

Le funzioni statiche non sono legate a oggetti particolari. Sono funzioni "generali" indipendenti dallo stato interno dell'oggetto.


I metodi statici non sono "garantiti per essere apolidi". Sebbene sia vero che non possono utilizzare i dati di istanza, hanno anche accesso ad alcuni stati (ovvero membri statici, entrambi della classe a cui appartiene il metodo statico e ad altri stati visibili globalmente come le variabili statiche di altre classi).

@delnan: vero ... hai ragione. Vorrei correggere questo adesso.
Dagnelies,

Senza statica: x.sin(). La tua risposta presuppone che il peccato dovrebbe essere una funzione di "matematica", mentre chiaramente sta operando su un doppio.
AjahnCharles il

0

Un po 'tardi qui, ma vorrei provare a creare una definizione precisa: le funzioni statiche sono funzioni che non fanno o non possono fare riferimento a proprietà / metodi dell'istanza della classe contenente.

In alcuni linguaggi, come C #, potrebbero esserci campi statici o proprietà in classi statiche, quindi non è esatto dire che non sono usati per lo stato; una funzione statica potrebbe fare uso dello stato statico (globale).

Fondamentalmente, si riduce a: le funzioni statiche, come qualsiasi cosa statica, sono utili quando ha senso che siano sempre disponibili senza dipendenza da istanze non statiche.

Le funzioni di supporto, come le funzioni matematiche, sono spesso un esempio, ma ce ne sono altre.

Se la classe creata richiede che i dati siano immutabili, potrebbe avere senso creare funzioni statiche che accettano un'istanza e passano una nuova istanza poiché l'istanza non può (o non dovrebbe) essere modificata. Le classi di stringa, ad esempio, potrebbero avere funzioni statiche che accettano una stringa (o 2 o più) e restituiscono una nuova stringa.

Un altro motivo potrebbe essere che esiste una classe che mantiene uno stato globale o dati di qualche tipo. Potrebbero esserci funzioni statiche che funzionano con le proprietà o i campi statici in quella classe statica.


0

Vorrei sottolineare un altro uso di static f ().

http://www.parashift.com/c++-faq/named-ctor-idiom.html

Si riduce a questo: le staticfunzioni consentono di creare "Costruttori nominati", ovvero denominare la funzione statica con un nome adatto e autocompattante, e questa funzione statica chiama uno dei costruttori (poiché i costruttori hanno nomi identici e si può avere un molti di loro, diventa difficile distinguerli).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.