5

C で C++ アクセス指定子 [public, private, protected] をエミュレートすることは可能ですか? より一般的には、C++ コンパイラは、クラスのプライベート メンバーが非メンバー関数によってアクセスされないようにするにはどうすればよいでしょうか?

4

3 に答える 3

5

C++ のアクセス制御は、完全にコンパイラの想像力の産物です。プライベート メンバーにアクセスできないのは、コンパイラがそうしようとするコードのコンパイルを拒否するためだけです。

ClassWithPrivateMemberのインスタンスへのポインターが実際にはのインスタンスへのポインターであるとコンパイラーに認識させることにより、C++ クラスのプライベート メンバーにアクセスするのは実際にはかなり簡単ClassWithPublicMemberです。してはいけないものへのアクセス。誰もそのようなことをするわけではありません...

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それは、ほとんどの人が(賢明にも)その内部を突き抜けないということです. そこでは、アクセス制御は単にあいまいさによって実施されます。

于 2012-06-13T03:08:36.003 に答える
4

別の回答(修正済みのため)で提案されているように、すべての型安全性を破棄する void* ポインターを使用しないことを強くお勧めします。代わりに、内容を指定せずにヘッダーで前方宣言することがstruct foo;できます。その後、ヘッダーで宣言されたインターフェイス関数の内外で、それらの構造体とポインターを渡すことができます。構造体の実装は、そのユニットの .c ファイル内に隠されています。

構造体と他のタイプ (int など) の間で変更するオプションを保持したい場合はtypedef、ヘッダーで を使用してインターフェイスのタイプをラップできます。

使用できる他の手法には、.c ファイル内で関数を宣言することが含まれますstatic。これにより、他のソースが関数を宣言している場合でも、他のソースからリンクできなくなります。

于 2012-06-13T03:37:11.617 に答える
1

目標を達成するには多くの方法がありますが、以下は私の方法です。

この例には、クラス「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);
}
于 2012-06-13T03:41:48.533 に答える