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.
Object-oriented design patterns in C and kernel development
161–170 of 224 posts
Re: Object-oriented design patterns in C and kernel development
#162Earlier 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 Smalltalk systems that stop being an issue after JITs got introduced.
Re: Object-oriented design patterns in C and kernel development
#163Earlier 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
Re: Object-oriented design patterns in C and kernel development
#164Earlier 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.
Re: Object-oriented design patterns in C and kernel development
#165Earlier 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.
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
#166Earlier 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.
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
#167Earlier 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…
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
#168Earlier 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…
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
#169Earlier 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.
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
#170Earlier 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…
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.