繁体   English   中英

在C中模拟访问说明符

[英]Emulate access specifiers in C

是否可以在C中模拟C ++访问说明符[public,private,protected]? 更一般地说,C ++编译器如何确保非成员函数不能访问类的私有成员?

C ++访问控制完全是编译器想象的一个例子:你不能只访问私有成员,因为编译器会拒绝编译任何试图这样做的代码。

通过欺骗编译器认为指向ClassWithPrivateMember实例的指针实际上是指向ClassWithPublicMember实例的ClassWithPublicMember - 即通过使用略微修改的头文件,您可以访问C ++类的私有成员实际上非常简单通常可以访问您不应该访问的内容。 并不是说有人做过这样的事......

在C中进行访问控制的最佳方法是将指针传递给opaque类型: struct对象,其定义不适用于客户端代码。 如果你提供一个foo* create_foo()方法和一系列的操作方法foo* ,隐藏的实际定义foo从客户端,那么你就必须取得类似的效果。

// File "foo_private.h"
struct foo {
    int private1;
    char private2;
};

// File "foo.h"
typedef struct foo foo;
foo * create_foo(int x, char y);
int mangle_foo(foo *);

// file "foo.c"
#include <stdlib.h>
#include "foo.h"
#include "foo_private.h"

foo * create_foo(int x, char y) {
    foo * f = (foo *) calloc(1, sizeof(foo));
    f->private1 = x;
    f->private2 = y;
}    

int mangle_foo(foo *f) {
    return f->private1 + f->private2;
}

现在,您将foo.cfoo.h一起分发到库中。 foo.h声明的函数形成一个类型的公共接口,但该类型的内部结构是不透明的; 实际上,调用create_foo()的客户端无法访问foo对象的私有成员。

我们的朋友FILE*是类似的东西,除了FILE类型通常不是真正不透明的。 只是大多数人(明智地)不会去探索它的内脏。 在那里,访问控制仅通过默默无闻来实施。

我建议强烈反对使用另一个答案中建议的void *指针,这会抛弃所有类型安全。 你可以改为向前声明struct foo; 在没有指定内容的头文件中,您可以将这些结构和指针传入和传出头部中声明的接口函数。 struct实现隐藏在该单元的.c文件中。

如果要保留在结构和其他类型(例如int)之间进行更改的选项,可以在标头中使用typedef来包装接口的类型。

您可以使用的其他技术包括在.c文件static内声明函数,以便它们不能与其他源链接,即使这些其他源声明了该函数。

有很多方法可以达到目标,以下是我的:

该示例包括类“struct test_t”和类函数“test_create”以及成员函数“print”

test.h:

struct test_t {
    // Member functions
    void (*print)(struct test_t *thiz);

    // Private attributes
    char priv[0];
};


// Class functions
struct test_t *test_create(int number);

test.c的:

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

// priv attr
struct test_priv_t {
    int number;
};


// member functions
static void print(struct test_t *thiz)
{
    struct test_priv_t *priv = (struct test_priv_t*)thiz->priv;
    printf("number = %d\n", priv->number);
}


// Class functions
struct test_t *test_create(int number)
{
    struct test_t *test = (struct test_t *)malloc(sizeof(struct test_t) + sizeof(struct test_priv_t));

    // setup member function
    test->print = print;

    // initialize some priv attr
    struct test_priv_t *priv = (struct test_priv_t*)test->priv;
    priv->number = number;

    return test;
}

main.c中:

#include "test.h"

int main()
{
    struct test_t *test = test_create(10);
    test->print(test);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM