Confirmed users
1,345
edits
Nnethercote (talk | contribs) |
Nnethercote (talk | contribs) |
||
| Line 110: | Line 110: | ||
=== An Example Involving Inheritance === | === An Example Involving Inheritance === | ||
Things are a little trickier when inheritance is involved | Things are a little trickier when inheritance is involved. An example: | ||
class B { | class B { | ||
virtual foo() { ... } | virtual foo() { ... } | ||
virtual | virtual size_t | ||
SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const | SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const | ||
{ | { | ||
| Line 126: | Line 126: | ||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); | return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); | ||
} | } | ||
// data members | |||
}; | }; | ||
| Line 131: | Line 133: | ||
virtual foo() { ... } | virtual foo() { ... } | ||
virtual | virtual size_t | ||
SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE | SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE | ||
{ | { | ||
| Line 138: | Line 140: | ||
return n; | return n; | ||
} | } | ||
virtual size_t | |||
SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE | |||
{ | |||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); | |||
} | |||
// data members | |||
}; | }; | ||
Things to note: | Things to note about <tt>SizeOfExcludingThis</tt>. | ||
* If <tt>D</tt> has data members that point to other objects, then <tt>D::SizeOfExcludingThis</tt> must override <tt>B::SizeOfExcludingThis</tt>. Otherwise, if we have a <tt>B*</tt> pointer that actually points to a <tt>D</tt> object, we'll end up calling <tt>B::SizeOfExcludingThis</tt> instead of <tt>D::SizeOfExcludingThis</tt>, and thus we'll fail to measure any objects that <tt>D</tt>'s fields point to. <tt>D::SizeOfExcludingThis</tt> must also call <tt>B::SizeOfExcludingThis</tt>, to ensure that any objects pointed to by fields inherited from <tt>B</tt> are measured. | |||
* <tt>D | * However, if <tt>D</tt> does not have any of its own fields that point to other objects, then <tt>D::SizeOfExcludingThis</tt> is not necessary. | ||
* <tt>D::SizeOfExcludingThis</tt> | * Alternatively, if <tt>D</tt> does have fields that point to other objects but you don't want to measure them because they're insignificant, then <tt>D::SizeOfExcludingThis</tt> is again not necessary. But it's a good idea to add a comment indicating this decision not to measure, and the names of the unmeasured fields. The obvious place for this comment is within <tt>D</tt>, but if <tt>B</tt> has many sub-classes like that, it might be easier to put the comment above <tt>B::SizeOfIncludingThis</tt>. | ||
Things to note about <tt>SizeOfIncludingThis</tt>. | |||
* | * <tt>D::SizeOfIncludingThis</tt> is identical to <tt>B::SizeOfIncludingThis</tt>. You might think that <tt>D</tt> could just inherit <tt>SizeOfIncludingThis</tt> from <tt>B</tt>. In some cases this works, but there's a lot of C++ subtlety involving the <tt>aMallocSizeOf(this)</tt> and whether <tt>this</tt> actually points to the start of the allocated object or somewhere in it's middle. This is doubly true if <tt>D</tt> features multiple inheritance. So, if in doubt, define <tt>D::SizeOfIncludingThis</tt> and you should be safe. | ||
* The <tt>MOZ_OVERRIDE</tt> | * The <tt>MOZ_OVERRIDE</tt> annotations say that <tt>D</tt>'s methods override the corresponding methods in <tt>B</tt>. On supporting compilers it gets expanded to the <tt>override</tt> keyword. It helps prevent accidentally having small differences in the function signatures (e.g. forgetting a <tt>const</tt>) that prevent the overriding from happening. | ||
=== Other Considerations === | === Other Considerations === | ||