The answer to Niel's leading question is clearly "C++", which invites the additional exercise "how practical would that be?".
My answer: I'm not sure. The i_op pointer would become an opaque method table pointer, however it is clearly impractical to rewrite every filesystem in C++, so C code would require require a variant definition of struct inode with an explicit definition of the opaque pointer, and the opaque vtable it references would need an explicit definition available to C code. These structures are pretty simple, it might be possible to emulate them in C.
I wrote a little program to test this theory. I defined a simple class with an integer field and a virtual function to increment that field. I know the vtable pointer is stored in the first word of a virtual object and by inspection I found that the first word of the vtable points at my member function. And I know that c++ passes the address of an object as a hidden parameter to any class member function. I stepped through a normal call to my virtual method to verify nothing mysterious is going on. Then I added some casts to retrieve the vtable pointer from an object, read the member address out of the vtable, and call that address as a function with one parameter, the object address. Aha, it works.
Whether this is a good idea is another question. This behavior is compiler dependent, but on the other hand there aren't a lot of compilers in the running when it comes to Linux kernel. It could probably be made to work. Not that I would seriously suggest rewriting the VFS in C++. Perhaps a device driver.