There is more to object oriented programming than v-tables but I record here about the first v-table structure that I learned of.

Early OS-360 operating systems, other than for a few of the smallest of the 360 models, provided a scheme to defer the kind of IO device that a program would use until the program came to the point of opening the file. Upon opening, a complex operation would occur that took into account information provided by the program, by the “Volume table of contents”, and the job control language. IBM supported several kinds of devices such as card readers, disks and tapes, and also several “access methods” for representing records within a file. Yet another orthogonal choice was whether the calls were synchronous. By open time it was known what sorts of calls for the file were in the program.

These choices were all fixed by file opening time. Upon opening a v-table was allocated. Routines specialized to these choices were dynamically loaded into memory and their addresses were placed in a v-table. Generic operations such as “READ”, “WRITE”, “CLOSE” would have fixed offsets within a v-table and these offsets were known at compile time. Device types and access methods were typically unknown at compile time.

In modern terms, the devices and access methods were polymorphic. Some compilers knew about this particular class by special compiler code. The class was welded into the language specs of at least PL/I and Cobol. Those languages did not support defining new classes.

I had contributed to the design of two IO systems before the 360. Both of these systems would probably have benefited from the idea. On the other hand opening a 360 file might take 50 disk accesses to support all of the mechanism in the general case. This problem was gradually alleviated as the system matured. I think that versions of the OS with these features may not have been delivered until 1966.

Here is more info.