> handle accesses to that function through the “class”, rather than the “object”
You don't need classes for OOP. C++ not putting methods that logically operate on an object, but don't need a pointer to it, into the automatically created vtable, is an optimization and an implementation detail. I don't know why you think that putting this function into a vtable precludes OOP.
Wait, how does inheritance work when the method is not in the vtable?
The calling convention for C++ non-static member functions always includes a this pointer, even if the function does not use it. Removing it on member functions that do not use it would pose a problem if another class inherited from this class and overrode the function definition with one that did use it. Maybe in very special cases whole program optimization could safely remove the this pointer, but it is questionable whether any compiler author would go through the trouble given that the exception handling would need to know about the change. Outside of whole program optimization, it is unlikely removing this from member functions that do not use it would ever happen because it would break ABI stability.
As for how inheritance works when the member function is not in the vtable, that depends on what kind of member function it is. All C++ functions are given a mangled name that is stuffed into C’s infrastructure for linking symbols. For static member functions, inheritance is irrelevant since they are tied to the class. Calls to static member functions go directly to the mangled function with no indirections, just as if it had been a global function. For non-static virtual member functions, you use the vtable pointer to find it. For non-virtual member functions, the call goes straight to the function as if a global function had been called (and the this pointer is still passed, even if the function does not use it), since the compiler knows the type and thus can tell the linker to have calls there go to the function through the appropriately mangled name. It is just like calling a global function.
> The calling convention for C++ non-static member functions always includes a this pointer, even if the function does not use it.
Yes. Since we are not in C++ we can choose to get rid of this useless pointer.
> Removing it on member functions that do not use it would pose a problem if another class inherited from this class and overrode the function definition with one that did use it.
That problem has nothing to do with the this pointer specifically. When you change the method signature of an inherited method you always have this problem. This simply means, that the superclass prescribes limits to subclasses, which is why it's possible to use a subclass inplace of a superclass.
> Maybe in very special cases whole program optimization could safely remove the this pointer, but it is questionable whether any compiler author
Yes, that's why its not done in C++, but we can do it, if we handroll it.
> it would break ABI stability
It does not if it has always been like this.
> For static member functions, inheritance is irrelevant since they are tied to the class. Calls to static member functions go directly to the mangled function with no indirections
In other words, ->check_flags() can't be implemented as a static member functions in C++. It would simply have a this pointer, that it just wouldn't use, since C++ has no way to express non-static member functions, that just don't take a this pointer.
> thus can tell the linker to have calls there go to the function
In our case the linker can only resolve the call to the appropriate vtable, since the type isn't known until runtime.
> Yes. Since we are not in C++ we can choose to get rid of this useless pointer.
If you were trying to implement OOP in the kernel in C and implemented a vtable, you cannot get rid of the this pointer in vtable entries since a child class might want to use it in the overrode definition. It is one of the same reasons why you cannot remove it in C++. The entire point of a vtable is to enable inheritance. If OOP really were being done, an out of tree module could make a class that inherits from this one without needing any code changes and use the this pointer, but you cannot do that if you drop the this pointer. I already explained this.
This is one interpretation. The other is that the interface of check_flags() specifies, that any implementation of it is only allowed to differ on the type of the object and not any other property.
You already prescribe with the chosen arguments in the superclass on which things the child implementation can depend. Why not also do this with the first argument?
You would typically put the this pointer into the first argument when doing OOP in C. You can put the this pointer in the last argument to have it work too. However, you cannot omit it entirely. That is something that is not OOP. It is an ADT.
So suppose you have it, but never use it. Then why have it you can just remove the first parameter. You can have object methods in C++ too, that don't use the this pointer.
Also why do you care exactly about the order of arguments? The nature of the function doesn't change, it's entirely arbitrary and orthogonal to the paradigm the function implements. Another example is the implementation of the equality operator between objects. In languages with syntactic sugar you typically have (self, other), but if its the true equality operator then the order doesn't matter.
You don't need classes for OOP. C++ not putting methods that logically operate on an object, but don't need a pointer to it, into the automatically created vtable, is an optimization and an implementation detail. I don't know why you think that putting this function into a vtable precludes OOP.
Wait, how does inheritance work when the method is not in the vtable?