C構造体は、関数を持っているように動作できますか?


13

struct構造体がメンバーを持つことはできますが、関数を持つことはできないCとs を使用します。簡単にするために、名前を付けた文字列の構造体を作成し、文字列のインデックスと位置の文字を置き換える文字をどこでstrできるようにするかを想定します。構造体は関数を持たないか、この動作を実装し、構造体が実際に構造体だけが新しい構造体にコピーして更新する(単純な)関数を持つことができることを模倣する方法がまだあるので、これは決して不可能でしょうか?それができるフィールド?str.replace(int i, char c)ici

したがってreplace、アクセスされたときなどに更新される新しい構造体を指す構造体の3番目のメンバーである可能性があります。できますか?それとも、私の意図を妨げる組み込みのものや、何らかの理論やパラダイムがありますか?

背景は、私がCコードを書いていることであり、OOP言語のライブラリビルトインであることがわかっている関数を再発明し、OOPは文字列とコマンドを操作する良い方法だと思います。


5
正直なところ、この種のことを行うには、無料の関数を作成した方が良いと思います。あなたが必要な元気を持っている場合は、読みcs.rit.edu/~ats/books/ooc.pdf
ロバート・ハーヴェイ

5
構造体には、関数へのポインタである変数を含めることができます。組み込みの継承はありませんが、同じシグネチャを持つ異なる関数を指すポインターを使用して構造体をインスタンス化できます。関数への最初のパラメーターを構造体へのポインターにしたいことがよくあります。
ジェームズマクロード

29
replace(&str、i、c)は本当に str.replace(i、c)よりもずっと悪いですか?あなたの質問機能の交換について、実際にはありませんが、それはCに新しい構文をしようとしているがどんなについてです
whatsisname

1
@RobertHarvey cs.rit.edu/~ats/books/ooc.pdf リンクをありがとう 。素敵な本(そして価格は正しいです)。
ジョンフォルコシュ16年

3
@whatsisname:Cでは、とにかく関数に構造体ポインターを渡す必要があるので、str.replace(&str, i, c)とにかく終わります。thisもちろん、C ++はポインターの受け渡しを自動化します。
ジョナサンレフラー

回答:


21

関数は次のようになります。

void
replace(struct string * s, int i, char c);

これは、最初のパラメーターとして操作するオブジェクトへのポインターを受け入れます。C ++では、これはthis-pointerと呼ばれ、明示的に宣言する必要はありません。(これをPythonと比較する必要がある場合)。

関数を呼び出すには、そのポインターも明示的に渡します。基本的に、o.f(…)構文と構文を交換しf(&o, …)ます。大したことではありません。

ポリモーフィズムvirtual関数とも呼ばれます)をサポートする場合、ストーリーはより複雑になります。また、Cでエミュレートすることもできます(この回答で示しました)。

ジャン・ヒューデックはコメントしている、あなたはまた、型名(つまりと関数名の接頭辞として、それ習慣にする必要がありますstring_replaceCには名前、スペースを持っていないので、これだけという単一の関数が存在することができます)replace


17
もちろん機能は、おそらくと呼ばれるようになりますstring_replaceCは、他のいくつかの持っている機能は、いずれかのオーバーロード、あなたがそうである必要はありませんので、replace...他のいくつかのタイプのために
ジャン・ヒューデック

2
名前を付けることはできませんstring_replace。始まる名前strmemまたはwcs小文字に続いては、将来の拡張のために予約されています。
デビッドコンラッド

43

構造体は関数ポインタを保持できますが、実際には仮想メソッドにのみ必要です。通常、オブジェクト指向Cの非仮想メソッドは、構造体を最初の引数として通常の関数に渡すことで実行されます。CのOOPフレームワークの良い例については、Gobject参照してください 。マクロを使用して、継承とポリモーフィズムに必要なボイラープレートの多くを処理します。

Cは44年前に作成されました。これは、オープンソースで非常に人気のある言語です。標準のC文字列は扱いにくいと考える最初の人ではありません。C文字列ライブラリを検索します。車輪を再発明する必要はありません。


2
他の注目すべき例はCPythonです。このコードは多くのOOPコンセプトを使用していますが、100%純粋なCです
。– Bakuriu

@Bakuriu私はあなたが混乱していると思うCythonCPythonの

1
@cat彼はおそらくPython C APIを意味し、Cythonは100%純粋なCではありません。docs.python.org/c
JAB

5
@catいいえ。CPythonソースを見てください。実際、ほとんどのことはOOPパラダイムを使用して行われ、それらはほとんどPython APIに一致するOOP APIを提供します。
バクリウ

1
@Bakuriuああ、あなたはPython言語ではなく、Pythonのランタイム、ソース、C APIを意味します。あなたのコメントはそれほど明確ではありませんでした
cat

8

関数ポインターを使用すると、次のことができます。

str.replace(&str, i, c);

これは一般に、実装が変更できる場合にのみ役立ちます。その場合、vtableを使用して、オーバーヘッドが構造体ごとに1つのポインターになるようにします。

str.vtable->replace(&str, i, c);

3
私はまだそれをstring_replace(&str、i、c)として呼び出し、呼び出しサイトにvtableについて知らせるのではなく、string_replace内でvtableを使用する傾向があります。
ピートカーカム

2
str(またはmemまたはwcs)で始まる@Pete名と小文字は、将来の拡張のためにC標準で予約されているため、呼び出さないでくださいstring_replacestr_replace結構です。
デビッドコンラッド

3

はい、できます。Cは、メモリ内の関数ブロックへのポインター、別名関数ポインターを許可し、それを使用して、ポリモーフィズムや仮想関数のようなインターフェイスを作成することができるという事実を利用できます(それほどきれいではない場合でも)。

最近、C and Goのインターフェイスのようなコードに関する私の学生の1人からの質問に続いて、このテーマに関するブログ投稿を書きました。ここで読むことができます。

非OOインターフェースに関するブログ投稿

アイデアが得られるかどうかを確認します。

また、コードに無料の関数を追加し、「this」ポインターを使用することもできます。つまり、他の回答で説明されているように、既存の構造体にポインターを渡して作業します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.