2012-04-25 17 views
7

Estoy trabajando en C, y tengo algunas variables que no quiero que sean globales, pero sí quiero tener los métodos get y set a los que se puede acceder "Globaly" afuera del archivo. Estoy acostumbrado a hacer esto en Java, pero C es muy diferente de esta manera. Básicamente, estoy buscando algo que siga este pseudo código, pero no he podido encontrar en ninguna parte ejemplos que pueda ver.C Variables privadas Obtener y establecer métodos

main.c 
#include data.h 
set(b); 

datalog.c 
#include data.h 
get(b); 

data.c 
private int c; 
set(b){ 
    c = b; 
} 
get(c){ 
    return c; 
} 
+0

'C' no tiene la noción de' privado'. Tal vez tratando de mirar las variables globales 'estáticas'. – RageD

+0

Así mi pregunta. ¿Cómo puedo engañar a C? – Reid

+0

Depende de lo que estés tratando de hacer. Como 'C' no es OOP (está orientado a funciones), tendrá que trabajar con funciones y' struct's o variables globales. – RageD

Respuesta

10

Usted hace la variable static. Cuando se crea una variable global static, su alcance está restringido al archivo actual.

Un ejemplo es el siguiente:

Nombre del archivo: main.c

#include <stdio.h> 

#include "header.h" 

extern int get(); 
extern void set(int); 

int main() 
{ 
    set(10); 
    printf("value = %d \n", get()); 
    set(20); 
    printf("value = %d \n", get()); 
    set(30); 
    printf("value = %d \n", get()); 
    set(40); 
    printf("value = %d \n", get()); 
    return 0; 
} 

Nombre del archivo: header.h

#include <stdio.h> 

int get(void); 
void set(int); 

Nombre del archivo: cabecera.c

#include "header.h" 

static int value = 0; 

int get(void) 
{ 
    return value; 
} 

void set(int new_value) 
{ 
    value = new_value; 
} 

Salida:

$ gcc -Wall -o main main.c header.h header.c 
$ ./main 
value = 10 
value = 20 
value = 30 
value = 40 
$ 
+1

No es necesario declarar 'get()' y 'set()' en la parte superior de 'main.c'. - Es por eso que creaste el encabezado en primer lugar. –

+2

No es necesario incluir 'stdio.h' en el encabezado. - El código en el encabezado no lo usa. –

+1

'header.c' - lol –

2

Puede escribir:

static int c; 

De esta manera, el ".o" no va a exportar la variable "c".

+0

Entonces, ¿podré acceder a esto desde las funciones get y set, pero no directamente? ES DECIR. ¿'Estático' cambia el alcance de la variable? – Reid

+1

'static' hace que una variable global solo sea visible dentro del módulo en el que está declarada. Por ejemplo, si otro módulo tiene 'extern int c', el vinculador no podrá encontrar" c ". – user1202136

7

Si desea variables privadas en c, hay una serie de técnicas que pueden aproximar una variable privada, pero el lenguaje C en realidad no tiene un concepto de "protección" que se extiende a privado, público, protegido (como C++ hace).

C mostrará el nombre de cualquier variable (que es un requisito en C) por lo que debe acercarse a él con la idea de ocultación de la información del tipo de la variable (toma de eliminación de referencias bastante difícil).

Un truco es definen la variable como un void* con el tipo de variable real que es conocido sólo en una .c módulo.

/* somefile.h */ 

extern void* counter; 

/* somefile.c */ 

#include "somefile.h" 

int actualCounter = 0; 
void* counter = &actualCounter; 

/* otherfile.c */ 

#include "somefile.h" 

// we can see "counter", but we cannot "use" it here; because we don't have access 
// to the real "hidden" type of "int". 

Un método mejor es extender esta idea usando la palabra clave struct, y hacer pseudo-métodos, al igual que

/* person.h */ 

struct s_person; 

typedef Person struct s_person; 

Person* new_Person(char* name); 
void delete_Person(Person* person); 

void Person_setName(Person* person, char* name); 
char* Person_getName(Person* person); 

/* person.c */ 

struct s_person { 
    char* name; 
}; 

Person* new_Person(char* name) { 
    Person* object = (Person*)malloc(sizeof(struct s_person)); 
    // duplicate the string for more security, otherwise constructor 
    // could manipulate the "private" string after construction. 
    object->name = strdup(name); 
    return object; 
} 

void delete_Person(Person* person) { 
    // some implementations pass a Person** to set the reference to 0 
    // this implementation requires that the caller sets his own references to 0 
    free(person->name); 
    free(person); 
} 

void Person_setName(Person* person, char* name) { 
    // free the old 
    free(person->name); 
    // duplicate the new to provide "out of simulated class" modification by malicious 
    // name setter. 
    person->name = strdup(name); 
} 

char* Person_getName(Person* person) { 
    // must return a copy, otherwise one can manipulate name 
    // from reference provided by Person_getName(...); 
    return strdup(person->name); 
} 

/* otherfile.c */ 

#include "Person.h" 

/* Now we can hold Person "simulated objects", but we cannot */ 
/* manipulate their "state" without using the C simulated object */ 
/* methods */ 

int main(int argc, char** argv) { 

    Person* bob = new_Person("bob"); 
    printf("%s\n", Person_getName(bob)); 
    delete_Person(bob); 
    // critical or we hold a pointer to freed memory. 
    bob = 0; 

    return 0; 
} 

Técnicas de este tipo tienen varias variantes, uno es tener una "estructura pública "con un puntero void * a la" estructura privada ". Uno es incluir los "métodos" como indicadores de función en la "estructura pública" (un paso hacia el polimorfismo de soporte), uno es escribir un sistema tipo C++ completo y adecuado que intente resolver las cosas exactamente como lo haría C++ (jerarquías de clase, polimorfismo, unión tardía, ocultamiento de información, etc.).

Básicamente, se puede conseguir un poco de "objeto-orientado-dad", sin demasiado trabajo, pero a medida que agrega más características de -ornamentation, se le agrega más código de unión (hasta que es mucho más sencillo de utilizar realmente una lenguaje de programación orientado a objetos).

+1

¿Es correcto: typedef Person struct s_person; ? Sería: typedef struct s_person Persona ;, ¿verdad? –

1

Por su ejemplo, se puede tratar de usar algunas struct con esta información. Un struct es como un class con solo public variables miembro (es decir, sin funciones). Así que considerar algo de la siguiente manera

#include <stdio.h> 

typedef struct _somestruct 
{ 
    int c; 
} theStruct; 

int getC(theStruct* obj) 
{ 
    if(obj == NULL) 
    return -1; 
    return obj->c; 
} 

void setC(theStruct* obj, int val) 
{ 
    if(obj == NULL) 
    return; 
    obj->c = val; 
} 

int main() 
{ 
    theStruct myStruct; 
    setC(&myStruct, 5); 
    printf("%d\n", getC(&myStruct)); 
    return 0; 
} 

Como se puede ver, C sólo funciona con objetos y funciones. Pero para obtener una variable global en todos los archivos, intente static int c = 0;

El ejemplo anterior es casi lo más parecido posible a una convención "java-style".

1
static int c; 

int get(void) { 
    return c; 
} 

int set(int n) { 
    c = n; 
} 
Cuestiones relacionadas