2010-09-20 14 views
14

Esiste un tale schema di dipendenze che sia impossibile mantenere tutto solo nei file di intestazione? Cosa succede se abbiamo applicato una regola di una classe solo per intestazione?È mai impossibile scrivere una libreria di sola intestazione?

Ai fini di questa domanda, cerchiamo di ignorare le cose statiche :)

+0

Cosa succede se la libreria senza header A dipende dalla libreria B di sola DLL? O è escluso dall'ultima frase? Ovviamente potresti sempre reimplementarlo come header, quindi forse non impossibile. – Skurmedel

+0

devi parlare con altre lingue? – Anycorn

+0

@Skurmedel: C++ non definisce alcuna funzione simile a DLL, quindi qualsiasi cosa verrà specificata per l'implementazione. Dubito che faccia alcuna differenza però. –

risposta

7

Sono consapevole di non funzioni in C++ standard, salvo statica che avete già menzionati, che richiedono una biblioteca per definire un'unità di traduzione completa (invece di solo intestazioni). Tuttavia, non è consigliabile farlo perché, quando lo fai, imponi a tutti i tuoi clienti di ricompilare l'intera base di codice ogni volta che la tua libreria cambia. Se si stanno utilizzando file di origine o una libreria statica o una forma di distribuzione di librerie dinamiche, è possibile modificare/aggiornare/modificare la libreria senza imporre la ricompilazione di tutti.

+4

"costringi tutti i tuoi clienti a ricompilare l'intera base di codice ogni volta che la tua libreria cambia" - ancor peggio, in pratica, li costringi a ricompilare la tua libreria ogni volta che cambia la base di codice. –

+4

Anche se rende la libreria banale da usare e aiuta il compilatore quando ottimizza. – GManNickG

+2

@GMan: dipende dal compilatore. IIRC, sia GCC che MSVC dispongono ora di funzionalità di generazione del codice di tempo di collegamento per build di release, che rimuovono la maggior parte (se non tutte) le potenziali differenze di prestazioni. –

2

La regola di una classe per intestazione non ha senso. Se questo non funziona:

#include <header1> 
#include <header2> 

poi qualche variazione di questa volontà:

#include <header1a> 
#include <header2> 
#include <header1b> 

Questo potrebbe risultare in meno di una classe per un colpo di testa, ma si può sempre usare (void *) e calchi e funzioni inline (nel qual caso il 'inline' sarà debitamente ignorato dal compilatore). Quindi la domanda, mi sembra, può essere ridotto a:

class A 
{ 
// ... 
void *pimpl; 
} 

E 'possibile che l'attuazione privata, Pimpl, dipende dalla dichiarazione di A? Se è così allora pimpl.cpp (come intestazione) deve entrambi precedere e seguire A.h. Ma dato che puoi sempre, ancora una volta, usare (void *) e cast e funzioni inline nelle intestazioni precedenti, può essere fatto.

Certo, potrei sbagliarmi. In entrambi i casi: Ick.

+2

Non vedo perché qualcuno dovrebbe utilizzare qualsiasi tipo di classe Pimpl in un'intestazione unica biblioteca, dato che l'idea se l'idioma Pimpl è quello di rompere le cose in unità di traduzione distinte ... –

+0

Sono d'accordo, non c'è nessun punto nel tentativo di fare una intestazione solo libreria quando l'implementazione è chiaramente inadatta ad essa. Forse non è quello che intendevi;) Ho inventato Pimpl come strumento per dimostrare che si poteva fare (usando la parola 'dimostra' molto liberamente). – paul

5

E 'possibile, direi, a condizione espressa di non utilizzare un numero di caratteristiche del linguaggio: come hai notato, alcuni usi della parola chiave static.

Potrebbe richiedere qualche trucco, ma possono essere esaminati.

  1. È necessario mantenere la distinzione di intestazione/origine ogni volta che è necessario interrompere un ciclo di dipendenze, anche se i due file saranno in pratica i file di intestazione.
  2. Le funzioni libere (non modello) devono essere dichiarate in linea, il compilatore potrebbe non essere in linea, ma se sono dichiarate, non si lamenteranno di essere state ridefinite quando il client crea la sua libreria/eseguibile.
  3. I dati condivisi a livello globale (variabili globali e attributi statici di classe) devono essere emulati utilizzando l'attributo statico locale nei metodi funzioni/classe. In pratica importa poco per quanto riguarda il chiamante (basta aggiungere ()). Si noti che in C++ 0x questo diventa il modo preferito perché fino ad allora è sicuro essere protetto dai thread fiasco dell'ordine di inizializzazione ... non è thread-safe;)

Rispettare questi 3 punti, credo che saresti in grado di scrivere una vera e propria libreria di intestazione (qualcuno vede qualcos'altro che mi è sfuggito?)

Un certo numero di librerie Boost ha usato trucchi simili per essere intestazione-solo anche se il loro codice era non completamente modello.Per esempio Asio fa molto coscientemente e propone l'alternativa utilizzando bandiere (vedi release notes for Asio 1.4.6):

  • clienti che hanno bisogno solo un paio di caratteristiche non devono preoccuparsi di costruire/collega, hanno solo afferrare che cosa hanno bisogno
  • i clienti che si affidano su di esso un po 'di più o vuole ridurre il tempo di compilazione viene offerta la possibilità di creare la propria libreria Asio (con i propri set di flag) e quindi includere intestazioni "leggere"

In questo modo (al prezzo di un ulteriore sforzo da parte degli sviluppatori della biblioteca) i clienti ricevono la loro torta e mangia anche questo. Penso che sia una soluzione carina.

Nota: mi chiedo se static funzioni potrebbero essere inline, io preferisco usare i namespace anonimi me quindi mai veramente guardato dentro ...

+0

re # 1: puoi disegnare uno scenario in cui sarebbe necessario? Ho provato a immaginarne uno, ma non sono riuscito a trovare nulla che non possa essere risolto spostando le definizioni di funzioni in linea dietro a tutte le definizioni necessarie. – sbi

1

Nella mia lunga carriera, non ho incontrato la dipendenza modello che non consentirebbe l'implementazione dell'intestazione.

Ricorda che se si dispone di dipendenze circolari tra classi, potrebbe essere necessario ricorrere a un'interfaccia astratta - paradigma di implementazione concreto o utilizzare modelli (utilizzando i modelli consente di definire le proprietà/metodi di riferimento dei parametri del modello, che sono risolto più tardi durante l'istanziazione).

Ciò non significa che DOVRESTI sempre cercare le librerie di solo intestazione. Per quanto validi, dovrebbero essere riservati a template e codice inline. NON DEVONO includere calcoli complessi e complessi.

Problemi correlati