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:
OatmealWhiskey
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`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.
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