I use C and struct
s where a struct can have members but not functions. Assume for simplicity that I want to create a struct for strings that I name str
and I want to be able to do str.replace(int i, char c)
where i
is the index of the string and c
is the character to replace the character at position i
. Would this never be possible since structs can't have functions or is there still some way we can implement this behavior and mimic that a struct could have a (simple) function that actually only is the struct copying itself to a new struct and updating its fields, which it could do?
So replace
could be a third member of the struct that points to a new struct that is updated when it is accessed or similar. Could it be done? Or is there something builtin or some theory or paradigm that prevents my intention?
The background is that I'm writing C code and I find myself reinventing functions that I know are library builtins in OOP languages and that OOP would be a good way to manipulate strings and commands.
4 Answers 4
Your function should look like this.
void
replace(struct string * s, int i, char c);
This accepts a pointer to the object to operate on as the first parameter. In C++, this is known as the this
-pointer and need not be declared explicitly. (Contrast this to Python where it has to.)
In order to call your function, you would also pass that pointer explicitly. Basically, you trade the o.f(...)
syntax for the f(&o, ...)
syntax. Not a big deal.
The story becomes more involved if you want to support polymorphism (aka virtual
functions). It can also be emulated in C (I've shown it for this answer.) but it ain't pretty to do by hand.
As Jan Hudec has commented, you should also make it a habit to prefix the function name with the type name (ie string_replace
) because C has no name-spaces so there can only be a single function named replace
.
-
18Of course the function will probably have to be called
string_replace
, because C does not have function overloading either and you are likely to have some otherreplace
for some other type...Jan Hudec– Jan Hudec2016年05月25日 08:05:47 +00:00Commented May 25, 2016 at 8:05 -
2It can't be named
string_replace
. Names beginning withstr
,mem
, orwcs
followed by a lowercase letter are reserved for future extensions.David Conrad– David Conrad2016年05月26日 06:07:23 +00:00Commented May 26, 2016 at 6:07
Structs can hold function pointers, but those are really only needed for virtual methods. Non-virtual methods in object-oriented C are usually done by passing the struct as the first argument to a regular function. Look at Gobject for a good example of an OOP framework for C. It uses macros to handle a lot of the boilerplate required for inheritance and polymorphism.
C was created 44 years ago. It's a very popular language for open source. You're not the first person to think standard C strings are clunky to work with. Do some searches for C string libraries. You don't have to reinvent the wheel.
-
2Other notable example is CPython. The code uses a lot of OOP concepts yet it's 100% pure C.Bakuriu– Bakuriu2016年05月25日 10:40:39 +00:00Commented May 25, 2016 at 10:40
-
-
1@cat He probably means the Python C API, Cython isn't 100% pure C. docs.python.org/c-api/intro.htmlJAB– JAB2016年05月25日 13:39:16 +00:00Commented May 25, 2016 at 13:39
-
5@cat No. Look at CPython sources. Most of the things are indeed done using the OOP paradigm, and they provide an OOP API that mostly matches the python API.Bakuriu– Bakuriu2016年05月25日 16:48:22 +00:00Commented May 25, 2016 at 16:48
-
1@Bakuriu Oh, you mean Python's runtime, source and C API not the Python language. your comment didn't make that very clearcat– cat2016年05月25日 20:01:16 +00:00Commented May 25, 2016 at 20:01
With function pointers, you can do:
str.replace(&str, i, c);
This is generally only useful if the implementation can change, in which case you should use a vtable so the overhead is only one pointer per struct:
str.vtable->replace(&str, i, c);
-
3I'd tend to still call it as string_replace(&str, i, c) then use the vtable inside string_replace rather than have the call site know about the vtable.Pete Kirkham– Pete Kirkham2016年05月25日 14:56:45 +00:00Commented May 25, 2016 at 14:56
-
2@Pete Names beginning with
str
(ormem
orwcs
) and a lowercase letter are reserved by the C standard for future extensions, so don't call itstring_replace
.str_replace
is fine.David Conrad– David Conrad2016年05月26日 06:11:19 +00:00Commented May 26, 2016 at 6:11
Yes, they can, sort of. You can make use of the fact that C allows for pointers to function blocks in memory, a.k.a. function pointers and using that you may create interface like polymorphism as well as virtual functions (even if it is not that pretty).
I wrote a blog post on this subject, following a question from one of my students, recently, pertaining to interface-like code in C and Go, you can read it here:
Blog post on non-OO interfaces
See if it gives you any ideas.
You could also just put a free function in your code, and use a "this"-pointer, meaning you pass a pointer to an existing struct to work on, as described in other answers.
str.replace(&str, i, c)
anyway. C++ automates the passing of thethis
pointer, of course.