Skip to content

Instantly share code, notes, and snippets.

@jki127
Created October 10, 2019 21:22
Show Gist options
  • Save jki127/a52fe8e0e0df68964ba8670b7cc35a59 to your computer and use it in GitHub Desktop.
Save jki127/a52fe8e0e0df68964ba8670b7cc35a59 to your computer and use it in GitHub Desktop.

Method Resolution - Programming Languages - Oct 8th, 2019

C++ Virtual Methods

class Ancestor {
    int x;
    public:
    Ancestor(int q) : x(q) {}
    virtual void breakfast() {cout<<"oatmeal";}
    void lunch() {cout<<"whiskey";} 
    virtual void dinner() {cout<<"steak";} 
};

class Derived : public Ancestor {
    int y;
    public:
    Derived(int w) : y(w), Ancestor(0) {}
    void lunch() {cout<<"avocado toast";}
    void dinner() {cout<<"quinoa";}
};

int main() {
    Ancestor *fred = new Ancestor(5);
    Ancestor *bob = new Derived(9);
    Ancestor *jane = new Derived(34);
    fred->breakfast();
    bob->lunch();
    jane->dinner();
    delete fred; delete bob; delete jane;
    return 0;
}

What does this program print?

Answer: Oatmeal
Whiskey
Quinoa

Bob and Jane have the static type of Ancestor and the dynamic type of Derived

Ancestor's VMT

  • A::breakfast
  • A::dinner

Derived's VMT

  • A::breakfast
  • D::dinner

How much memory do the variables in main take up? 4 or 8 bytes since they are all pointers.

What do each of these variables point to? fred

  • VMTP to Ancestor's VMT
  • x=5

bob

  • VTMP to Derived's VMT
  • y=9
  • x=0

jane

  • VMTP to Derived's VMTP
  • y=34
  • x=0

How many parameters are passed to breakfast and dinner?

Answer: 1 parameter which is the instance itself or `this`

Never call a virtual method in a C++ constructor

The reason why we never call a virtual method in the contstructor of a C++ class is because the VMT has not been set-up. A class' VMT is set-up at the end of the constructor.


Python Method Resolution

class Foo:
	def __init__(self):
		self.x = 9
		self.y = 3
	
	def another(self):
		print("Hi")
	
	def method(self, z):
		self.x = z*#
		return z*2

class Splat(Foo):
	def method(self, w):
		self.x = 99
		return 0

 f = Foo()
 f.method() # which of these two methods will be called?
 f.__dict__ # returns dict containing variables of f
 f.__class__.__dict__ # returns dict containing methods and their corresponding addresses in memory

 s = Splat()
 s.another()
 s.__dict__ # returns variables of s
 s.__class_.__dict # returns a dict of the methods defined in Splat
 # another() will not be in the dict above
 # if python cannot find it in the current classes dict, it will 
 # keep looking in the ancestor's class dict
 s.__bases__ # returns dict of the ancestors of Splat

In python, classes are also objects. All instances have a method __class__ that return a dict of the object produced by the class definition.

__bases__ returns a dict of the ancestor classes of the current object.

All classes in python are derived from a master class called Object.

Every time you call a method in python it looks for the method in:

  • the dict of the class of the object
  • the class(es) of the ancestor(s) of the object in the order of which they are derived in (ex: class test(first, second):
  • the class of the ancestor of the ancestor and so on...

#proglang-f19

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment