Capstone: Inheritance, Polymorphism and Memory, Explained

UPI Study › Courses › C++ Programming › Free lessons › Lesson 11.7 Free with a free account

Capstone: Inheritance, Polymorphism and Memory

C++ Programming · Chapter 11: Inheritance and PolymorphismSection 11.7 · lesson 84 of 84video coming soon

← Hand-Crafting Linked Lists

Earn 3 college credits for C++ ProgrammingRecommended for credit by NCCRS · Computer Science 242 · self-paced · one payment, lifetime access

In this lesson

Applied challenge: a payroll register.

  • An abstract base with derived types that answer differently
  • One container of base handles, dispatching at run time
  • Memory owned clearly and released on every exit path
  • Records saved, reloaded as the right kind, behind a robust menu

Transcript

Everything said in the video, section by section (1,658 words). Read along, or search it.

Opening Question

One Loop, Three Answers, No Leaks

Nothing new appears in this section. This is one project that needs almost everything built so far to work at the same time. A hierarchy with genuine dispatch, memory obtained and correctly returned, records that survive the program ending, and an interface a person can actually use. The individual pieces are familiar. Making them cooperate is the exercise. So here's the question to carry through it: what has to be true for one loop to give three employees three different answers, and leak nothing?

Prior Material

Every Requirement Reuses Earlier Topics

Every requirement is something you've already covered. The type hierarchy draws on members, access sections, and inheritance modes. Different answers to one request need the marking that makes a call consult the object, rather than the handle. A mixed container needs vectors and pointers. Memory that's returned needs ownership and the destructor. Data that outlives the run needs files and fixed-length records. A usable interface needs the menu loop and input checking. And a markable submission needs the specification, planned tests, and milestones. The synthesis is the new part.

Project Brief

Building an Abstract Payroll Register

The brief: build a payroll register. It holds a workforce of mixed kinds, and computes what each person is owed for the month. It saves to a file, reloads on the next run, and is driven from a menu. The base, employee, is abstract. It holds the id and name, and declares two requests: describe yourself, and what are you owed. Salaried and hourly employees are required. Commissioned is a stretch goal. Each kind answers the same two requests differently.

Pay Rules

Figures Your Test Runs Must Reproduce

Here are the pay rules, with the figures your test runs must reproduce. Salaried pay is the annual salary divided by twelve. Nine hundred sixty thousand rupees a year gives eighty thousand. Hourly pay is rate times hours, with hours above one hundred sixty paid at one and a half times. At two hundred fifty rupees an hour for one hundred seventy hours, that's forty-three thousand seven hundred fifty. For one hundred twenty hours, thirty thousand. Commissioned pay is a retainer plus a percentage of sales. Twenty thousand, plus eight percent of five hundred thousand, gives sixty thousand.

Requirement A

Abstract Base With Marked Requests

Requirement A is the hierarchy. The base must be abstract. At least one request is declared without an answer, so no base object can be created. Both requests are marked so that a call through a base handle reaches the actual object's version. The base destructor is marked the same way. Without it, releasing a derived object through a base handle skips the derived clean-up. Shared data, the identifier and name, belongs in the base. Data specific to one kind belongs in that kind. And every replacement in a derived type carries override, so the compiler checks the signature.

Requirement B

Dispatch Across a Mixed Container

Requirement B is the whole point of the exercise, in a few lines. A vector of employee pointers holds a salaried employee, Anita, and hourly ones, Ravi and Meera, plus Dev on commission. One loop asks each to describe itself, and prints its pay. One loop, one call, and different behavior per element. Every figure matches the pay table. If your output prints the same description for every entry, the marking on the base declarations is missing. That single symptom is the difference between this project working, and merely compiling.

Requirement C

Memory Released Once on Every Path

Requirement C is memory, and here are the rules it's marked against. Every block obtained is released exactly once. The container's blocks were obtained one at a time, and nothing releases them automatically. The base destructor is marked for dispatch, because elements are released through base handles. Check it with derived destructors that print. Pointers are set to nothing after release, during shutdown, and when an entry is deleted. A later read must fail visibly, not quietly. And release happens on every exit path, because the menu has several ways to end, including an error path.

Demo

Releasing Elements Through Base Handles

Here is that check running. After the listing, release every element through its base handle. Each derived destructor announces itself, so a line appears for every object. Then the register is cleared, and the pointers are set to nothing.

Common Mistake

The Silent Leak From Unmarked Destructors

One of those rules catches most people. Releasing a derived object through a base handle runs only the base clean-up, unless the base destructor is marked for dispatch. Nothing warns you. The program runs, the output is right, and the leak is silent, and per object. Strictly, it's undefined behavior, so we never run it. The compiler can warn, though, and here is its real warning for the unmarked destructor. So prove yours works. Print a line from each derived destructor, and check that those lines appear when the container is emptied.

Requirement D

Fixed-Shape Tagged Records in Files

Requirement D is persistence, and it's the design problem this project is really built around. A file holds bytes. It doesn't hold types. Writing three kinds of object into one file, and reading them back, means recording in the file which kind each record was. So every record has the same fixed shape: a tag, an id, a name, and two values, whose meaning depends on the tag. One record: the same size whatever the kind. For a salaried record, value A is the annual salary. For hourly, it's the rate and the hours. For commissioned, the retainer and the month's sales.

Save and Load

Writing Records and Rebuilding Objects

Saving walks the container, asks each element for the values that describe it, fills one tagged record, and writes it. The record must be a plain, fixed-size type. Objects are never written directly. Loading reads one record at a time, looks at the tag, builds an object of the matching kind, and adds its handle to the container. An unrecognized tag is reported and skipped, never assumed. And a part-read record ends the load. Run it: the register is released, then reloaded from the file, and every kind comes back as itself, with the same pay.

Design Rationale

Why Objects Are Not Written Directly

Why not just write the object out? It carries the machinery that makes dispatch work. Read back on another run, it isn't a valid object at all. So convert to a plain record on the way out, and construct a real object on the way in. That conversion is the persistence layer.

Requirement E

Eight Menu Options and Their Pitfalls

Requirement E is the interface, with eight required options. Add an employee, list everyone with pay, find or remove by identifier, show the payroll total, save, load, and quit. Option seven is the one worth planning. Loading over an existing register must release what's already held first, or every load leaks the previous contents. Option four must release the block before removing the handle. Remove first, and the address is gone. And quit releases everything before ending.

Requirement F

One Type Per Pair of Files

Requirement F is file organization, with one type per pair of files. The employee files hold the abstract base, included by everything else. The salaried and hourly files each hold one derived kind, and include the base header. The register files hold the container, its operations, and saving and loading. That's where the memory rules live. And main holds only the menu loop and input handling. No pay rules, and no file work.

Milestones

Seven Runnable Steps Over Fifteen Hours

Here are the suggested milestones, each ending in something that runs. Allow roughly fifteen hours, across several sittings. Start with the specification and design sketches. Then the base and one derived kind, with one object describing itself. Then the second kind and the dispatch loop, where two kinds print two different descriptions. Then memory correctness, then saving and loading, where save, quit, restart and load brings back the right kinds. Then the menu and input handling, then the split across files. And finally, testing and the write-up.

Submission

What to Hand In With Evidence

Here's what to submit. The specification's four lists, and design sketches dated before the code. The source, building cleanly with warnings enabled, along with the exact build command. Testing evidence: every figure in the pay table, a save, quit, restart and load transcript, and invalid inputs refused. Memory evidence: your own block count at shutdown, plus leak-checked runs for at least two exit paths. A design write-up of six hundred to nine hundred words. And a milestone log with part-built versions, assembled as you go, not reconstructed at the end.

Marking Rubric

Seven Dimensions That Must All Pass

The rubric has seven dimensions, and a passing submission must be sound on every row. Hierarchy design: an abstract base, data where it belongs, and every replacement checked by the compiler. Dispatch: one loop over base handles with genuinely different behavior. Memory: clean leak checks, with derived clean-up demonstrably running. Persistence: mixed kinds reload as the correct kinds. Interface robustness: bad input refused, without ending the program. Organization: the required file split. And evidence: expected values computed by hand, and a write-up that explains decisions rather than describing code.

Final Checklist

Checks to Run Before Submitting

Before you submit, check each of these. Creating a base object directly is rejected by the compiler. If it isn't, the base isn't abstract. Here is that check, with a base object added to main. The listing loop prints different descriptions for different kinds. Each derived destructor announces itself when the register is emptied, and leak checks report nothing lost. A saved file reloads every kind correctly, even after the program has closed. And loading twice in a row doesn't increase the memory held. Finally, every figure in the pay table is reproduced exactly.

Quick Check

Same Description for Every Employee

Quick check. A classmate's listing prints the same description for every employee, yet it builds without a single error. Which two rules from Requirement A did that code break? Pause and think. First, describe isn't marked virtual in the base, so the call is decided by the handle's type, not the object's. Second, the derived versions don't carry override. With it, the compiler would have refused the build, and pointed straight at the mistake.

Key Takeaways

Marked Base, Owned Blocks, Tagged Records

To close. Build an abstract base with marked requests and a marked destructor, and write override everywhere. Hold everything in one container of base handles, and let one loop ask each element to answer as itself. Own every block, and release it once, on every path. And write tagged plain records out, constructing real objects back in.

About C++ Programming at UPI Study

C++ Programming (Computer Science 242) is a self-paced online course of 84 video lessons in 11 chapters, from your first program to decisions, loops, arrays, functions, classes, files, pointers and inheritance. It carries a NCCRS credit recommendation for 3 semester credits.

Every lesson transcript is free on pages like this one, and the videos are free with a free UPI Study account. Enrolling adds a practice quiz after each lesson, the graded work and final exam that earn the credit, lifetime access, and an official transcript on completion. UPI Study has helped over 130,000 students with college credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Why take it here

Why students take C++ Programming with UPI Study

Your first real programming languageC++ teaches how programs really work: variables, control flow, functions, memory and objects. It is the base for data structures, algorithms, systems and game programming, and for most computer-science degrees.
Credit at a fraction of the priceThe same 3 credits can cost $750 or more at a US college. Here it is one payment, self-paced, with lifetime access.
Finish your degree soonerTransfer credits reduce the courses you still owe, so you can graduate earlier or lighten a heavy semester.
Strengthen an applicationA completed college-level course on an official transcript shows admissions and scholarship committees you can do the work.
Study on your own scheduleNo start dates, no deadlines. Watch the lessons, practice, and take the final when you are ready.
130,000+students helped with college creditsACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Where the credit goes

Universities that work with NCCRS

C++ Programming carries a NCCRS credit recommendation. These universities work with NCCRS; some are UPI Study's signed partners. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.

Find my college → Not listed? Ask Athena in the corner of this page, or book a 15-minute call.

FAQ

Questions students ask us

About Capstone: Inheritance, Polymorphism and Memory

Why does my C++ loop over base-class pointers print the same description for every derived object?
The usual cause is that the request is not declared virtual in the base class, so the call is resolved by the pointer's type instead of the actual object. Mark the function virtual in the base. Also add override in each derived version, because then the compiler rejects a mismatched signature instead of quietly building.
Why does a base class destructor need to be virtual when deleting derived objects through base pointers?
Deleting a derived object through a base pointer needs a virtual base destructor so the derived clean-up runs. Without it, the behavior is undefined, and in practice the derived part may never be cleaned up. The program may still seem to work and print correct output, so the leak is silent. Printing a line from each derived destructor lets you confirm it runs.
How do you save and reload objects of different derived classes from one binary file in C++?
Convert each object to a plain, fixed-size record that begins with a tag naming its kind, then write that record. File bytes do not store types, so the tag is essential. When loading, read one record, check the tag, construct an object of the matching class, and add its pointer to the container. Skip and report unknown tags.
What memory mistakes should I avoid when a C++ menu program manages a vector of base-class pointers?
Release every block exactly once, on every exit path. Loading over an existing register must first delete the old objects, or each load leaks. When removing an entry, delete the object before erasing its pointer, because erasing first loses the address. Set pointers to nullptr after release so a later read fails visibly, and release everything on quit.

About the C++ Programming course

How many college credits is C++ Programming?
C++ Programming (Computer Science 242) carries a NCCRS credit recommendation for 3 semester credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.
How much does C++ Programming cost and what is included?
$250, paid once, with lifetime access: all 84 video lessons, a practice quiz after each, the graded work and final exam, and an official transcript when you finish. Students who want several courses choose UPI Study PRO instead.
Which universities accept UPI Study credits?
UPI Study has signed partner agreements with universities such as Thomas Edison State University, University of the People and Charter Oak State College, and works with universities such as Penn State, SNHU and SUNY. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities. Use "Find my college" on this page to check yours.
How long does C++ Programming take?
It is self-paced with no deadlines. The 84 lessons total about 0 hours of video; most students add reading and practice time and finish in a few weeks to a few months, on their own schedule.
How are the exams done?
Quizzes and assignments are online in the course. The final exam is taken online with proctoring; a person on the UPI Study team checks assignments, usually within two days.
How do my credits reach my college?
When the course shows 100% complete, request the official transcript from your dashboard. It is sent to the college you name, and you can send it to more than one. Check your college first with "Find my college" on this page, or ask Athena.

Ready for the full course? Earn 3 credits in C++ Programming.

84 video lessons, a quiz after each one, and the graded work that earns the credit. Recommended for credit by NCCRS.

C++ Programming
3 credits · NCCRS
Enroll →