在C语言中是否可能模拟C++的访问权限修饰符[public, private, protected]?更广义地说,C++编译器如何确保类的private成员不被非成员函数访问?
在C语言中是否可能模拟C++的访问权限修饰符[public, private, protected]?更广义地说,C++编译器如何确保类的private成员不被非成员函数访问?
C++的访问控制完全是编译器的想象:你不能访问一个私有成员,只是因为编译器会拒绝编译任何试图这样做的代码。
事实上,通过欺骗编译器认为指向ClassWithPublicMember
实例的指针实际上是指向ClassWithPrivateMember
实例的指针,即通过使用稍微修改的头文件,通常可以访问C++类的私有成员。不过,没有人会做那样的事情...
在C语言中进行访问控制的最佳方法是传递指向不透明类型的指针: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.c
与foo.h
一起分发。在foo.h
中声明的函数形成类型的公共接口,但该类型的内部结构是不透明的;实际上,调用create_foo()
的客户端无法访问foo
对象的私有成员。
我们的朋友FILE*
也是类似的东西,只不过FILE
类型通常并不是真正的不透明。只是大多数人(明智地)不会去研究它的内部结构。在那里,访问控制仅通过模糊性来强制执行。void*
抛弃了类型安全性。有更好的方法来解决这个问题。 - blueshifttypedef struct f foo;
和 struct foo;
(未使用?),而 create_foo
仍然返回 void
。你测试过了吗..? - blueshift有很多方法可以实现目标,以下是我的方法:
示例包括一个类“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);
}