C中的内联Setter和Getter函数

时间:2014-01-24 18:16:38

标签: c inline encapsulation getter-setter data-hiding

在C ++中,我可以在头文件中内联声明一个getter函数:

class Cpp_Example
{
  public:
    unsigned int get_value(void)
    { return value;}
  private:
    unsigned int value;
};

通过包含此头文件,客户端方法和函数可以使用getter函数来访问私有变量。

我希望用C语言对这个概念进行建模:
hello.h:

#ifndef HELLO_H
#define HELLO_H
#include <stdio.h>

inline void Print_Hello(void)
{
    extern const char hello_text[32];
    puts(hello_text);
}


inline void Print_Value(void)
{
    extern unsigned int value;
    printf("Value is: %d\n", value);
}

#endif // HELLO_H

hello.c:

const char hello_text[32] = "Hello World!\n";

static unsigned int value = 5U;

main.c:

#include <stdio.h>
#include <stdlib.h>

#include "hello.h"

int main(void)
{
    Print_Hello();
    Print_Value();
//  puts(hello_text);
    return EXIT_SUCCESS;
}

我从gcc收到链接器错误:

$ gcc -o main.exe main.c hello.c
/tmp/cc41ZB8H.o:main.c:(.rdata$.refptr.value[.refptr.value]+0x0): undefined reference to `value'
collect2: error: ld returned 1 exit status

有没有办法让内联函数(在头文件中)访问另一个翻译单元中的静态变量?

或者有没有办法实现内联的getter函数?

我在嵌入式平台上使用IAR Embedded Workbench,ARM7TDMI处理器 gcc编译器用于测试PC上的概念。

编辑1:背景
我正在寻找优化关键部分内的getter调用。目标是减少在关键部分花费的时间。

编辑2:无全局
我们的商店使用的编码指南没有全局变量 此外,该系统是运行MicroCOSII的RTOS。

5 个答案:

答案 0 :(得分:2)

首先,与在C ++中使用私有变量的方式相同,您可能意味着拥有struct而非全局变量的私有变量。有了这个假设,这里有一个你可以使用的模型:

/* some_type.h */
struct some_type
{
    int public_data;
    void *privates;
};

struct some_type_privates
{
    char hello[32];
    int value;
};

inline const char *get_hello(struct some_type *t)
{
    struct some_type_privates *p = t->privates;
    return p->hello;
}

inline int get_value(struct some_type *t)
{
    struct some_type_privates *p = t->privates;
    return p->value;
}

/* similarly for setters */

与私有变量及其getter和setter在头文件中的方式相同,您也可以在C中执行此操作。


另一方面,我建议不要尝试在C语言中编写C ++。虽然C ++喜欢使事情复杂化以防止白痴破坏某些东西,但另一方面C相信程序员有一定程度的智能。这些假设是否合理不是讨论的问题。但我的意思是,C的精神不是隐藏变量,以致程序员不会错误地访问它。

也就是说,这就是你通常在C中创建结构的方式:

struct some_type
{
    int public_data;
    char hello[32];     /* read only */

    /* internal */
    int value;
};

(当然有足够的文档)告诉任何程序员她不应该写hello但是可以自由地阅读它(你试图通过内联getter实现的)。它还告诉value是私有的,所以程序员不应该读或写它。

您可以在许多带有或返回结构的POSIX函数中看到这一点。有些不需要控制访问权限的人可以自由修改结构,例如stat。有些需要检查输入的人有设置器,例如pthread_attr_*

答案 1 :(得分:1)

您需要删除static关键字。 static定义为local to the compilation unit

答案 2 :(得分:0)

正如Shabbas所写,它在C中并没有真正起作用。 关键字 inline 意味着静态,即使编译器实际上没有内联它。如果它是如此短的功能,它可能会内联它。但关键是,如果它不是静态的,它甚至不能考虑内联它,因为函数需要在外部可见,它需要一个地址,内联函数没有。 由于它在编译单元中是本地的,因此它只能处理编译单元内部已知的内容。因此你需要说一下 value 变量,就像你需要在C ++标题中提到它一样,只有在C中没有 private 这样的东西。 您不能在相同的情况下使用内联和数据隐藏,既不能在C中也不能在C ++中。

答案 3 :(得分:0)

假设您的意思是全局的,静态分配的变量,您可以这样做:

在Example.h中:

#ifndef Example
#define Example
  extern int getValue();
#endif

在Example.c中

#include "Example.h"

static int value;

inline int getValue() {
    return value;
}

// All the functions in Example.c have read/write access

在UsesValueExample.c

#include "Example.h"

// All the functions in UsesValueExample.c have read-only access

void printValue() {
    printf("value = %d", getValue());
}

如果您想获得幻想并强制所有代码通过getter和setter访问,例如如果变量是volatile,并且你想大力鼓励所有方法使用变量的本地缓存来避免访问volatile的开销,那么:

在VolatileExample.h中:

#ifndef VolatileExample
#define VolatileExample
  extern int getValue();
#endif

在VolatileExample.c中

#include "VolatileExample.h"

void setValue(); // Forward declaration to give write access

// All the functions in VolatileExample.c have read/write access via getters and setters

void addToValuesAndIncrementValue(int const values[], int const numValues) {
    int value = getValue(); // Cache a local copy for fast access

    // Do stuff with value
    for (int i = 0; i < numValues; i++) {
        values[i] += value;
    }
    value++;

    // Write the cache out if it has changed
    setValue(value);
}

// Put the definitions after the other functions so that direct access is denied

static volatile int value;

inline int getValue() {
    return value;
}

inline void setValue(int const newValue) {
    value = newValue;
}

在UsesVolatileValueExample.c

#include "VolatileExample.h"

// All the functions in UsesVolatileValueExample.c have read-only access

void printValue() {
    printf("value = %d", getValue());
}

答案 4 :(得分:0)

这是我用来隐藏全局变量的模式。

在某些头文件中,例如module_prefix.h,您声明以下内容:

typedef int value_t;  // Type of the variable

static inline value_t get_name(void)    __attribute__((always_inline));
static inline void    set_name(value_t) __attribute__((always_inline));

static inline value_t get_name(void) {
    extern value_t module_prefix_name;
    return module_prefix_name;
}

static inline void set_name(value_t new_value) {
    extern value_t module_prefix_name;
    module_prefix_name = new_value;
}
/* Note that module_prefix_name is *no longer* in scope here. */

当然,您必须在某些编译单元中定义module_prefix_name不使用 static关键字,如上所述,例如在module_prefix.c中,您有以下内容:

#include "module_prefix.h"
value_t module_prefix_name = MODULE_PREFIX_NAME_INIT_VALUE;

这与Thomas Matthews尝试使用的模式基本相同,深入了解本质并确保编译器始终内联函数,并且不会不必要地生成显式函数体。注意使用module_prefix作为穷人的名字空间。