C结构的行为可以像具有功能一样吗?


13

struct在结构可以有成员但没有函数的地方使用C和s。为简单起见,假设我要为我命名的字符串创建一个结构,str并且我希望能够在str.replace(int i, char c)哪里完成i该操作,该操作是字符串的索引,也是c替换位置上的字符的字符i。因为结构体没有功能,或者我们仍然可以通过某种方式实现这种行为并模仿结构体可以具有(简单)功能的事实,这实际上仅仅是结构体将自身复制到新结构体并更新其结构体,所以这将永远不可能吗?字段,它可以做什么?

因此,replace可能是该结构的第三个成员,该成员指向一个新的结构,该新结构在访问或类似的操作时会更新。能做到吗?还是有些内在的东西或某种理论或范例阻止了我的意图?

背景是我正在编写C代码,并且发现自己正在重新发明一些我所知道的函数,这些函数是OOP语言中的内置库,而OOP将是一种处理字符串和命令的好方法。


5
老实说,我认为编写自由函数来做这种事情会更好。但是,如果您有必要的帮助,请阅读cs.rit.edu/~ats/books/ooc.pdf
罗伯特·哈维

5
结构可以包含作为函数指针的变量。没有内置继承,但是您可以使用指向具有相同签名的不同函数的指针实例化结构。您经常需要使函数的第一个参数成为结构的指针。
James McLeod

29
replace(&str,i,c)真的比str.replace(i,c)差很多吗?你的问题实际上不是有关更换功能,它是关于努力斯马什-一种新的语法为C.
whatsisname

1
@RobertHarvey感谢您访问 cs.rit.edu/~ats/books/ooc.pdf 链接。好书(价格合适)。
John Forkosh '16

3
@whatsisname:在C语言中,无论如何都必须将结构指针传递给函数,因此无论如何还是要结束str.replace(&str, i, c)。当然,C ++自动执行this指针的传递。
乔纳森·勒夫勒

Answers:


21

您的函数应如下所示。

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

这接受指向对象的指针作为第一个参数进行操作。在C ++中,这称为this-pointer,无需显式声明。(将此与必须使用的Python进行对比。)

为了调用您的函数,您还应该显式传递该指针。基本上,您将o.f(…)语法f(&o, …)换成语法。没什么大不了的。

如果您想支持多态(也称为virtual函数),那么故事会变得更加复杂。它也可以用C进行仿真(我已经为这个答案显示了它。)但是用手工做起来并不好。

正如Jan Hudec所评论的那样,您还应该养成在函数名称前加上类型名称(即string_replace)的习惯,因为C没有命名空间,因此只能有一个名为的函数replace


17
当然,该函数可能必须被调用string_replace,因为C也不具有函数重载,并且您可能还replace需要一些其他类型的重载…
Jan Hudec

2
无法命名string_replace。以strmemwcs后跟小写字母开头的名称保留给以后的扩展。
戴维·康拉德

43

结构可以容纳函数指针,但实际上只有虚拟方法才需要。面向对象C中的非虚拟方法通常是通过将struct作为第一个参数传递给常规函数来完成的。在 Gobject上可以找到C的OOP框架的一个很好的例子。它使用宏来处理继承和多态性所需的许多样板。

C创建于44年前。这是一种非常流行的开源语言。您不是第一个认为标准C字符串难以使用的人。搜索C字符串库。您不必重新发明轮子。


2
其他值得注意的例子是CPython。该代码使用了很多OOP概念,但它是100%纯
C。– Bakuriu

@Bakuriu我想你混淆用CythonCPython的

1
@cat他可能表示Python C API,Cython并非100%纯C。docs.python.org/c-api/intro.html
JAB

5
@cat号。请查看CPython源码。实际上,大多数事情都是使用OOP范例完成的,它们提供了一个与python API最匹配的OOP API。
巴库里

1
@Bakuriu哦,您的意思是Python的运行时,源代码和C API,而不是Python语言。您的评论并不太清楚
猫,

8

使用函数指针,您可以执行以下操作:

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

通常,这仅在实现可以更改的情况下才有用,在这种情况下,应使用vtable,这样每个结构的开销仅为一个指针:

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

3
我倾向于将其仍称为string_replace(&str,i,c),然后在string_replace中使用vtable,而不是让调用站点知道该vtable。
皮特·柯坎

2
C标准为以后的扩展保留了以str(或memwcs)开头的@Pete名称以及小写字母,因此请勿调用它string_replacestr_replace很好
戴维·康拉德

3

是的,他们可以的。您可以利用以下事实:C允许使用指向内存中功能块的指针(也称为函数指针),并使用它可以创建多态性以及虚函数之类的接口(即使它不是那么漂亮)。

我写了一篇有关该主题的博客文章,紧接着我的一个学生提出了一个问题,该问题与C和Go中类似接口的代码有关,您可以在这里阅读:

非OO接口上的博客文章

看看是否有任何想法。

您还可以只在代码中放置一个自由函数,并使用“ this”指针,这意味着您将指针传递给要处理的现有结构,如其他答案所述。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.