【C言語】構造体を隠蔽する

275, 2019-12-29

目次

構造体の隠蔽と、内部リンケージな関数のテスト。animal.c に対し、ヘッダファイルを二つ用意。animal_public.hは公開し、animal_private.hは非公開なヘッダファイル。利用者側は公開されているヘッダファイルをインクルードして使う。

書いてみて思った隠蔽のメリット

  • 利用者側が構造体の実体を宣言・定義できない。
  • アロー演算子などでメンバにアクセスできない。
  • 利用者側がデータ構造とその扱いを気にする必要がない。

書いてみて思った隠蔽のデメリット

  • ヘッダファイルを二つも書くのはめんどくさい。

FILE構造体とf*系の関数のそれにそっくり。

テストしたソースコード。

// main.c
#include "animal_public.h"
#include <stdio.h>

int
main(void)
{
    Animal* animal = animal_new( 10 );

    // Animal animal_2 = {};
    // error: variable ‘animal_2’ has initializer but incomplete type
    // error: storage size of ‘animal_2’ isn’t known

    // animal->age = 20;
    // error: dereferencing pointer to incomplete type

    // animal_private();
    // main.c:(.text+0x21): undefined reference to `animal_private'

    animal_set_age( animal, 30 );

    printf( "age: %d\n", animal_get_age( animal ) );// age: 30

    animal_delete( animal );
    return 0;
}
// animal_public.h
#ifndef INCLUDED_ANIMAL_PUBLIC_H
#define INCLUDED_ANIMAL_PUBLIC_H

typedef struct Animal Animal;

Animal* 
animal_new( const int age );

void 
animal_delete( Animal* animal );

int 
animal_get_age( Animal* animal );

void 
animal_set_age( Animal* animal, const int age );

#endif/*INCLUDED_ANIMAL_PUBLIC_H*/
#ifndef INCLUDED_ANIMAL_PRIVATE_H
#define INCLUDED_ANIMAL_PRIVATE_H

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

struct Animal{
    int age;
};

#endif/*INCLUDED_ANIMAL_PRIVATE_H*/
// animal.c
#include "animal_private.h"

 // ---- private functions ---- 

static void 
animal_private( void )
{
    printf( "call animal_private()\n" );
}

 // ---- public functions ---- 

Animal* 
animal_new( const int age )
{
    Animal* animal = ( Animal* )malloc( sizeof( Animal ) );
    if( !animal ) {
        perror( "failed to allocate memory" );
        exit( EXIT_FAILURE );
    }

    animal->age = age;

    return animal;
}

void 
animal_delete( Animal* animal )
{
    free( animal );
    animal_private();// debug
}

int 
animal_get_age( Animal* animal )
{
    return animal->age;
}

void 
animal_set_age( Animal* animal, const int age )
{
    animal->age = age;
}


$ gcc -std=c11 -Wall main.c animal.c
$ ./a.out 
age: 30
call animal_private()

Webアプリケーションの制作ならNARUPORT

Webアプリケーションの制作ならNARUPORTにお任せください。
Webアプリの他にもGUIアプリやChromeExtension, スクリプトの制作など可能です。
以下のお問い合わせフォームからご依頼ください!

投稿者名です。64字以内で入力してください。

必要な場合はEメールアドレスを入力してください(全体に公開されます)。

投稿する内容です。

スポンサーリンク

スポンサーリンク

スポンサーリンク

スポンサーリンク