C Частные переменные Get и Set методы
Я работаю в C, и у меня есть некоторые переменные, которые я не хочу, чтобы они были глобальными, но я хочу иметь методы get и set для них, к которым можно получить доступ "Globaly" вне файла. Я привык делать это в Java, но C сильно отличается в этом смысле. В основном я ищу что-то, что следует за этим псевдокодом, но я не смог найти нигде с примерами, на которые я мог бы взглянуть.
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;
}
6 ответов
Вы делаете переменную static
, Когда глобальная переменная сделана static
, его область ограничена текущим файлом.
Пример таков:
Имя файла: 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;
}
Имя файла: header.h
#include <stdio.h>
int get(void);
void set(int);
Имя файла: header.c
#include "header.h"
static int value = 0;
int get(void)
{
return value;
}
void set(int new_value)
{
value = new_value;
}
Выход:
$ gcc -Wall -o main main.c header.h header.c
$ ./main
value = 10
value = 20
value = 30
value = 40
$
Если вам нужны закрытые переменные в c, есть ряд методов, которые могут аппроксимировать закрытые переменные, но в языке C на самом деле нет концепции "защиты", которая распространяется на закрытые, публичные, защищенные (как это делает C++).
C покажет имя любой переменной (это требование в C), поэтому вы должны подойти к ней с идеей информации, скрывающей тип переменной (что делает разыменование довольно трудным).
Один трюк состоит в том, чтобы определить переменную как void*
фактический тип переменной известен только в одном .c
модуль.
/* 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".
Лучший способ - расширить эту идею, используя struct
ключевое слово и создайте псевдо-методы, например
/* 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;
}
Методы, подобные этой, имеют несколько вариантов, один из них - иметь "публичную структуру" с указателем void* на "приватную структуру". Один из них заключается в том, чтобы включить "методы" в качестве указателей на функции в "публичную структуру" (шаг к поддержке полиморфизма), а другой - на самом деле написать полную и правильную систему типов C++, которая пытается разрешить вещи точно так же, как C++ (иерархии классов, полиморфизм, позднее связывание, сокрытие информации и т. д.).
По сути, вы можете получить некоторую "объектно-ориентированность" без особой работы, но по мере добавления дополнительных возможностей -ornamentation вы будете добавлять больше связующего кода (пока на самом деле гораздо проще фактически использовать объектно-ориентированный язык программирования).,
Вы можете ввести:
static int c;
Таким образом, ".o" не будет экспортировать переменную "c".
static int c;
int get(void) {
return c;
}
int set(int n) {
c = n;
}
Вы можете улучшить ответ @RageD, используя указатели функций:
#ifndef MYCLASS_H
#define MYCLASS_H
/********************************* MyClass.h **********************************/
typedef struct MyClass {
int Value;
int (*GetValue)(); // Don't specify arguments
void (*SetValue)(); // Don't specify arguments
} MyClass_t;
// Make the default class accessible to other modules
extern MyClass_t new_MyClass;
#endif
/********************************* MyClass.c **********************************/
#include <stdio.h>
static int getValue(MyClass_t* obj){
if(obj == NULL)
return -1;
return obj->Value;
}
static void setValue(MyClass_t* obj, int value){
if(obj == NULL)
return;
obj->Value = value;
}
// Default "constructor" of MyClass
MyClass_t new_MyClass = {0, &getValue, &setValue};
/*********************************** main.c ***********************************/
#include "MyClass.h"
int main(){
// Create a default instance of the class
MyClass_t myClass = new_MyClass;
// Call the private (static) Getter function --> Prints 0
printf("%d\n", (*myClass.GetValue)(&myClass));
// Set the instance's value by the Setter function
(*myClass.SetValue)(&myClass, 9);
// Prints 9
printf("%d\n", (*myClass.GetValue)(&myClass));
return 0;
}
На вашем примере вы можете попробовать использовать некоторые struct
с этой информацией. struct
это как class
только с открытыми переменными-членами (т.е. без функций). Итак, рассмотрим что-то следующее
#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;
}
Как вы видете, C
работает только с объектами и функциями. Но чтобы получить глобальную переменную для всех файлов, попробуйте static int c = 0;
Приведенный выше пример почти так же близок, как вы можете прийти к соглашению "в стиле Java".