Inheritance
Inheritance
Define relationships between objects:
• Has-a
• Is-a
----------
3 Types of Views
Note: The views are unofficial - they are used to gain a better understanding of the material.
Logic View
“Has -a”
An instance of A contains at least 1 instance of B
class B
{
};
class A
{
B obj;
};
/* A is in a "has-a" relationship with B*/
{
};
class A
{
B obj;
};
/* A is in a "has-a" relationship with B*/
“Is-a”
D “is-a” B
D can be accessed as if D is a B
class D:B
{
}
/*D is in a "is-a" relationship with B */
{
}
/*D is in a "is-a" relationship with B */
Memory View
Important: A and D have the exact memory layout.
Language View
• Syntax
• Types of Inheritance
• Figure out how members access our result.
----------
3 Access Specifiers for Inheritance
1. Public inheritance
Syntax:
struct B { int x; int y; };
class D : public B
{
void foo()
{
D d;
d.x=10;
d.y=20; /*This is okay.*/
this->x =30;
this->y = this->x;
//All the above are okay.
}
}
D d;
d.x = d.y; //This is also okay even though it's outside the sscope - this is because it is public.
class D : public B
{
void foo()
{
D d;
d.x=10;
d.y=20; /*This is okay.*/
this->x =30;
this->y = this->x;
//All the above are okay.
}
}
D d;
d.x = d.y; //This is also okay even though it's outside the sscope - this is because it is public.
class D: public B { ... };
D can be publicly used as if it is a B.
Any scope can use D as if it is a B.
2. Protected inheritance
• Protected inheritance can only be accessed by the derived class and it's descendants.
Syntax:
class D2: protected B {};
class D3: protected B { D3 d3; d3.x = d3.y; /*this is okay*/
D2 d2; d2.x = d2.y; /* this is not okay! */
}
//Explanation: D3 is using B even though protected inheritance means that x and y can only be accessed by the derived class and its descendants; neither of whom are D3.
//Another note: D3 cannot be created because D3 has not yet been defined but that's a nitpick.
class D4: protected D2 {D4 d4; d4.x=d4.y //this is okay
D2 d2; d2.x = d2.y; //not okay! Since we're dealing with x and y D4 can only use itself as B but it cannot use D2 as a B.
}
D2 d2;
d2.x = d2.y; /*This does NOT WORK, results in compile time failure */
class D3: protected B { D3 d3; d3.x = d3.y; /*this is okay*/
D2 d2; d2.x = d2.y; /* this is not okay! */
}
//Explanation: D3 is using B even though protected inheritance means that x and y can only be accessed by the derived class and its descendants; neither of whom are D3.
//Another note: D3 cannot be created because D3 has not yet been defined but that's a nitpick.
class D4: protected D2 {D4 d4; d4.x=d4.y //this is okay
D2 d2; d2.x = d2.y; //not okay! Since we're dealing with x and y D4 can only use itself as B but it cannot use D2 as a B.
}
D2 d2;
d2.x = d2.y; /*This does NOT WORK, results in compile time failure */
3. Private inheritance.
• Private inheritance means that the inheritance can only be accessed by the derived class itself and no other scope.
Why use inheritance?
//Before inheritance:
void update_all_objects(std::vector<Object> &v)
{
for(auto& elem: v)
elem.update();
}
//After inheritance:
void update_all_objects(std::vector<Object *> &v)
{
for(auto& elem: v)
elem->update();
}
void update_all_objects(std::vector<Object> &v)
{
for(auto& elem: v)
elem.update();
}
//After inheritance:
void update_all_objects(std::vector<Object *> &v)
{
for(auto& elem: v)
elem->update();
}