- Η δυνατότητα χωρισμού ενός προγράμματος σε ανεξάρτητες λειτουργικές
μονάδες επιτρέπει τον ορισμό αφηρημένων οντοτήτων στις οποίες η
πρόσβαση γίνεται μόνο μέσω συναρτήσεων και με συγκεκριμένο τρόπο.
- Η χρήση των οντοτήτων αυτών γίνεται μόνο μέσω των συναρτήσεων και
των τύπων που ορίζονται σε αντίστοιχο αρχείο επικεφαλίδων,
ενώ η υλοποίηση γίνεται σε ξεχωριστό αρχείο C.
Ο τρόπος αυτός προγραμματισμού ξεχωρίζει την υλοποίηση από τους μηχανισμούς
πρόσβασης επιτρέποντάς μας να αλλάξουμε την υλοποίηση χωρίς να επηρεαστεί
το υπόλοιπο πρόγραμμα.
- Το παρακάτω παράδειγμα ορίζει έναν μετρητή ο οποίος μπορεί
μόνο να αυξάνεται:
/*
* Header file
*/
extern int get_counter(void);
extern void inc_counter(void);
/*
* C file
*/
static int counter;
int
get_counter(void)
{
return (counter);
}
void
inc_counter(void)
{
counter++;
}
- Το παραπάνω παράδειγμα δημιουργεί έναν μόνο μετρητή.
Με τη χρήση δεικτών και δυναμικής μνήμης μπορούμε να ορίσουμε ένα
εργοστάσιο που να δημιουργεί απεριόριστο αριθμό από μετρητές.
Ο αφηρημένος τύπος του μετρητή παριστάνεται ως ένας δείκτης σε
ακέραιο:
/*
* Header file
*/
typedef int *counter;
extern counter new_counter(void);
extern int get_counter(counter c);
extern void inc_counter(counter c);
/*
* C file
*/
/*
* Return a new counter object
*/
counter
new_counter(void)
{
counter c;
c = (counter)malloc(sizeof(int));
*c = 0;
return (c);
}
int
get_counter(counter c)
{
return (*c);
}
void
inc_counter(counter c)
{
(*c)++;
}
- Με τη χρήση των παραπάνω αρχείων μπορούμε να προγραμματίσουμε
με δύο λ.χ. μετρητές:
#include <stdio.h>
#include "counter.h"
main()
{
counter c1, c2;
c1 = new_counter();
c2 = new_counter();
inc_counter(c1);
inc_counter(c1);
inc_counter(c2);
printf("%d %d\n", get_counter(c1), get_counter(c2));
}
- Το παραπάνω παράδειγμα επιτρέπει σε κάποιον να διαβάσει στο
αρχείο των επικεφαλίδων ότι ο αφηρημένος τύπος είναι ένας δείκτης
σε ακέραιο και να τον μεταβάλει με λάθος τρόπο (πχ *c = 12;).
Μπορούμε να διασφαλίσουμε τον αφηρημένο τύπο από τέτοιου είδους
προσβάσεις ορίζοντας μια δομή στο αρχείο υλοποίησης
και μόνο έναν δείκτη στη δομή αυτή στο αρχείο επικεφαλίδων
(η γραφή structptr->member είναι συντομογραφία της (*structptr).member):
/*
* Header file
*/
typedef struct s_counter *counter;
extern counter new_counter(void);
extern int get_counter(counter c);
extern void inc_counter(counter c);
/*
* C file
*/
struct s_counter {
int value;
};
/*
* Return a new counter object
*/
counter
new_counter(void)
{
counter c;
c = (counter)malloc(sizeof(struct s_counter));
c->value = 0;
return (c);
}
int
get_counter(counter c)
{
return (c->value);
}
void
inc_counter(counter c)
{
c->value++;
}
- Είναι αξιοσημείωτο ότι η παραπάνω (διαφορετική) υλοποίηση συνεχίζει
να είναι συμβατή με το πρόγραμμα το οποίο χρησιμοποιεί τους δύο δείκτες.