2

私はOOCでこのpdfの最初の数章を読んでいます:http ://www.planetpdf.com/codecuts/pdfs/ooc.pdf

ここで、Stringクラスを実装しようとしました。私はファイルに使用しました:main.cとnew2.h。

これはmain.cです:

#include "new2.h"
#include <stdio.h>

int main(){

    void * stringObject = new2(String,"a");

    printf((*stringObject).text);
}

これはnew2.hです(この作業を行うために必要だと思った必要不可欠なもの以外はすべて削除したため、空白のコードを含みます)。

#include <stdarg.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>


struct Class{
    size_t size;
    void * (* ctor)(void * self, va_list * app);
//  void * (* dtor)(void * self);
//  void * (* clone)(const void * self);
//  int (* differ)(const void * self, const void * b);

};

struct String{
    const void * mClass;//must be first
    char * text;

};

static void * String_ctor (void * _self, va_list * app)
{
    struct String * self = _self;
    const char * text = va_arg(* app, const char *);
    self->text = malloc(strlen(text)+1);

    assert(self->text);
    strcpy(self->text,text);
    return self;

}

static const struct Class _String ={
    sizeof(struct String),
    String_ctor

};



const void * String =&_String;



void * new2(const void * _class,...)
{
    const struct Class * mClass = _class;
    void * p = calloc(1,mClass->size);

    assert(p);
    *(const struct Class **)p = mClass;

    if(mClass -> ctor)
    {
        va_list ap;

        va_start(ap,_class);
        p=mClass->ctor(p, &ap);
        va_end(ap);
    }

    return p;

}

new2.hのすべての関数は、pdfリンクから逐語的に取得されています。gccを使用してコマイルしようとすると、警告が表示されます。voidポインターを逆参照していますが、文字列が共用体または構造体ではないため、main.cで文字列のテキストを呼び出せないというエラーが発生します。

正直なところ、new2.hは紛らわしいと思います。私が言ったように、私はpdfから関数をコピーしました。これが私が起こると思うことです:

  1. new2が呼び出されます。引数Stringは、Class構​​造体へのポインターを作成し、それをnew2.hで既に作成されているString構造体を指すようにコンピューターに指示します。
  2. Stringオブジェクトに十分なメモリを割り当てます。
  3. コンストラクター(String_ctor)を呼び出し、変数引数リストを使用してchar引数(この場合は「a」)を取得します。

私の理解はあいまいで、このコードはコンパイルされません。どんな助けでもいただければ幸いです!

4

1 に答える 1

2

このコードをコンパイルするには

 void * stringObject

 struct String * stringObject

そうしないと、コンパイラは .text フィールドのアドレスを特定できません。

struct Stringメソッドを返す理由の 1 つvoid*は、継承を提供することです。呼び出し元のプログラムだけが、 のどのサブクラスstruct Stringが使用されているかを知っています。

この本の例はvoid * stringObject、String クラスの「パブリック」インターフェイスのみを使用し、内部に入ってそのプライベート メンバーにアクセスすることはないため、そのまま使用できます。

文字列を出力する別の方法は、文字列を出力するメソッドでクラスを拡張するか、「フレンド」関数を定義することです。

于 2012-06-03T05:19:27.117 に答える