Live data from Hacker News

Object-oriented design patterns in C and kernel development

oshub.org

161–170 of 224 posts

Re: Object-oriented design patterns in C and kernel development

#161

Earlier quoted context omitted.

> In Smalltalk and Objective-C, you just check at runtime whether an object instance responds to a message. This is the original OOP way. This introduces performance issues larger than the typical ones associated with vtable lookups. Not all domains can afford this today and even fewer in the 80s/90s when these languages were first designed. > It's sad that OOP was corrupted by the excessively class-centric C++ and J…

When you fear about the branch miss, then you can also just call the method and catch the SIGSEGV. I think if you allow for the possibility of there being no implementation, then you can't really not have some decision there. This would also apply for say a C++ virtual method.

A SIGSEGV is not guaranteed when calling an address that does not have a function.

Re: Object-oriented design patterns in C and kernel development

#162
post #6

Earlier quoted context omitted.

In Smalltalk and Objective-C, you just check at runtime whether an object instance responds to a message. This is the original OOP way. It's sad that OOP was corrupted by the excessively class-centric C++ and Java design patterns.

> In Smalltalk and Objective-C, you just check at runtime whether an object instance responds to a message. This is the original OOP way. This introduces performance issues larger than the typical ones associated with vtable lookups. Not all domains can afford this today and even fewer in the 80s/90s when these languages were first designed. > It's sad that OOP was corrupted by the excessively class-centric C++ and J…

In NeXTSTEP it was fast enough to have the whole OS, including device drivers, written in Objective-C.

In Smalltalk systems that stop being an issue after JITs got introduced.

Re: Object-oriented design patterns in C and kernel development

#163
post #18
post #11

Earlier quoted context omitted.

My point is that this pattern is not object oriented programming. As for a default behavior with it, you usually would do that by either always adding the default pointer when creating the structure or calling the default whenever the pointer is NULL. In the Linux VFS for example, there are optimized functions for reading and writing, but if those are not implemented, a fallback to unoptimized functions is done at th…

To be fair, OOP is not 100% absolutely perfectly defined. Strustrup swears C++ is OOP, Alan Key, at least at some point laughed at C++, and people using CLOS have yet another definition

You forgot about people using BETA, or Self, or ......

Re: Object-oriented design patterns in C and kernel development

#164
post #111

Earlier quoted context omitted.

> like instantiation with unimplemented functions I think this is more of an effect of C distinguishing between allocating memory (aka object creation) and initialization, which other languages disallow for other reasons, not because there are not OOPy enough.

Unlike OOLs, C does not enforce contracts around structures (objects). You are free to do literally anything you want to them.

Including implementing Abstract Data Types, thus everything on the structs is only accessible via functions that enforce the contracts.

Re: Object-oriented design patterns in C and kernel development

#165
post #152

Earlier quoted context omitted.

As it isn't the compiler that creates the vtable, you can also have the equivalent of this as the last parameter or where you want it to be. > It could also contain variables that are non-pointers. The convention of it being a pure vtable is that it just doesn't. > Neither is allowed in a vtable Who is the vtable membership authority? :-)

You can take the API for a linked list and implement a balanced binary search tree behind it, but continuing to call it a linked list after doing that is wrong. Similarly, you can do pointer indirections the same way a vtable would do them, but if the things you get are not the equivalent of member function pointers, it is not a vtable.

> In computer programming, a virtual method table (VMT), virtual function table, virtual call table, dispatch table, vtable, or vftable is a mechanism used in a programming language to support dynamic dispatch (or run-time method binding). (Wikipedia)

When its a table of function pointers used for dynamic dispatch, to me it's a vtable. I don't care about their type signatures as long as they logically belong to the object in question.

You seem to have a different very narrow definition of vtables, so the discussion is kind of useless.

Re: Object-oriented design patterns in C and kernel development

#166

Earlier quoted context omitted.

When you fear about the branch miss, then you can also just call the method and catch the SIGSEGV. I think if you allow for the possibility of there being no implementation, then you can't really not have some decision there. This would also apply for say a C++ virtual method.

A SIGSEGV is not guaranteed when calling an address that does not have a function.

Are you talking about C? In C it's not guaranteed whether a non existing function will result in an actual function call. As soon as an actual function call was generated by the compiler, a modern CPU is very likely to trap.

We are talking about an optimization of a language implementation here. This would be very much written in a ASM or another language were this is defined.

Re: Object-oriented design patterns in C and kernel development

#167
post #114

Earlier quoted context omitted.

You can implement OOP in C as you can in any language, the article is an example of this. C is not an OOP language in any way, it doesn't have any syntactic features for it and use the term "object" for something different.

The article mentions file_operations, but ignores that it has what would be a static member function in C++ in the form of ->check_flags(), which is never in a vtable. The article author is describing overlap between object oriented programming and something else, called data abstraction, which is what is really being done inside Linux, and calling it OOP. You can implement OOP in C if you do vtables for inheritance…

I honestly don't think how a C++ compiler chooses to implement an object method does matter here.

It's a function belonging to an object, to which is dynamically dispatched with something I would call a vtable. To me that sounds like a classic example of OOP.

Data abstraction is a core of OOP.

This pattern can be used to implement inheritance, when it isn't here that doesn't mean its not OOP.

Re: Object-oriented design patterns in C and kernel development

#168

Earlier quoted context omitted.

That sounds like a case of the Liskov substitution principle.

Yes it is, but the point is that without the contract being defined, we can't apply the principle; the details of the interface contract determine what it means to be substitutable. The LSP is never absolute in a practical system. Because why would you have, say, in a casee of inheritance, a Y which is an new kind of X, if all it did was substitute for X, and behave exactly the same way? Just use X and don't create Y…

> if all it did was substitute for X, and behave exactly the same way?

LSP is about behaviour existing in the supertype. Adding behaviour doesn't violate LSP.

> In a graphics program, an ellipse and rectangle are substitutable in that they have a draw() method and others, so that they plug into the framework.

The behaviour in question means it draws something. It can draw something different every time, and not violate LSP here.

Re: Object-oriented design patterns in C and kernel development

#169
post #154

Earlier quoted context omitted.

The term "vtable" is not exclusive to C++. Trait function dictionaries in Rust are called vtables and behave as described here, there's not necessarily any 'this' or 'self' object.

The point of the vtable is to allow dynamic dispatch based on the actual type of an object. When you have a function that does not need a this pointer, it no longer depends on the type of the object and putting it in there anyway could cause you to execute a variant depending on the type of the object, which seems like a buggy undesirable behavior.

It can still depend on the type, the answer just doesn't need information from the instance.

What speed limits can this road possibly have is a question I want to ask about this specific road. Yet this can be answered by referring to the country, which is already known when you create the road. But the user that asks this question can still ask this about roads in different countries, so this question still is valid.

Different objects can have different methods. When the method to be used is known at the time of object creation it can be chosen by assigning the appropriate function pointer in the vtable. The method itself might not necessarily need a instance pointer though.

Re: Object-oriented design patterns in C and kernel development

#170
post #153

Earlier quoted context omitted.

I would still call it a vtable. Who assures you that every function of a class needs a pointer to the object instance? When you don't need it, you can just leave it of when you roll your own.

Static member functions are tied to the class while virtual member functions are tied to the object. If you throw the static member functions into a vtable, you will at best have a bug where the static member function from a different class can be called. Alternatively, you would have an undefined behavior where the other class in the hierarchy does not implement this function. There is a saying “If Your Only Tool Is…

> Static member functions are tied to the class while virtual member functions are tied to the object.

That's nice, but the entire point is, that the caller doesn't know the type of the object, it only has a supertype. That's why you need dynamic dispatch here. Of course you can implement dynamic dispatch without function pointers, but it is done with function pointers here. If you don't want to name dynamic dispatch implemented with function pointers a vtable, OK, that's fine, but that's the definition I am familiar with.

Post reply on HN