Project 9

Stewardship Account

Apologetic question: "What does Christianity say about money?"

Project 9 — Stewardship Account

“Each one must give as he has decided in his heart, not reluctantly or under compulsion, for God loves a cheerful giver.” — 2 Corinthians 9:7

Chapter: 9 — From Struct to Class Due: End of Week 9 Submit: A link to your code — an OnlineGDB project URL or a public GitHub repo URL — with stewardship.cpp as the main source file. See Appendix D for the full workflow. Allowed tools: Everything through Chapter 9 — types, conditionals, loops, functions, arrays, structs, classes with public/private and methods. Required (Normal) tier uses only Chapter 9 tools. Some Medium-tier features preview later concepts — pointers (Ch 11) for M2’s linked accounts; see the preview note in the feature. No constructors with arguments (Ch 10) or inheritance (Ch 12) anywhere.


The Setup

There’s a Christian word for how to handle resources that aren’t fundamentally your own: stewardship. The Old and New Testaments both treat the picture: a master entrusts his servants with talents and expects an account. The master is God. The talents are everything you have — money, time, gifts, attention, life itself. The expectation is faithful handling, not maximizing wealth.

This project asks you to model that idea in code. A stewardship account is a bank account with the picture made explicit. Three kinds of outflow:

  • Spend — money used for your own needs and expenses.
  • Give — money given to others, to the church, to the poor.
  • Save — money set aside for prudent future needs.

A struct has no rules. A class enforces them. This project’s whole point is that a class enforces rules a struct can’t.

A direct word before you start. This project does not endorse the prosperity gospel. Generosity isn’t modeled as a path to material reward. The class doesn’t reward you when you give. There’s no “tithe and your balance goes up.” There’s just an honest record of what came in, what went where, and what’s left. That’s what stewardship has always actually meant.

A second direct word. The class will enforce some rules but it will not legislate your conscience. It rejects negative deposits because that’s nonsensical. It rejects overdrafts because that’s bankruptcy. It does not refuse to let you spend more than you give — that’s not the class’s call. The class makes the record honest. You decide what to do with the truth.


Learning Targets

By completing this project, you will demonstrate that you can:

  • Declare a class with private fields and public methods.
  • Write methods that enforce invariants on the class’s data.
  • Maintain class state across multiple method calls.
  • Pass a class object by value, by reference, and const &.
  • Distinguish “data” and “behavior” — and put behavior next to the data it operates on.
  • Write a main that exercises a class without violating its encapsulation.

Normal Tier

Goal: A StewardshipAccount class with deposits, gifts, expenses, and a clean ledger printout. Run a demo in main that exercises every method.

Required features

  1. Class declaration with private fields:

    class StewardshipAccount {
    private:
        double balance;
        string owner;
    public:
        void init(string n, double starting);
        void deposit(double amount);
        void give(double amount);
        void spend(double amount);
        void print_statement();
        double get_balance();   // public read-only access
    };
  2. Method behaviors:

    • init — sets owner and starting balance. Negative starting balance is set to 0 (with a printed message).
    • deposit(amount) — adds amount to balance. If amount <= 0, prints “Rejected: deposit must be positive.” and does nothing.
    • give(amount) — subtracts amount from balance. Rejects negatives and overdrafts.
    • spend(amount) — same as give, but tracks the operation under a different label.
    • print_statement() — prints the current owner and balance in a clean format.
    • get_balance() — returns the current balance (read-only access for any external code that needs to see the balance).
  3. Crucially: give and spend must be separate methods even though they do similar things. The class must internally know which kind of outflow happened — even if Normal tier doesn’t yet track a per-transaction log.

  4. A main that runs at least 10 operations across at least 2 accounts. Include at least one rejected operation and at least one transfer-style interaction (call give on account A and deposit on account B with the same amount — this approximates Account A giving to Account B).

  5. No direct access to balance or owner from main. All interaction is through public methods. The grader will check.

  6. Compiles cleanly with -Wall -Wextra enabled. No warnings.

Example output

=== Stewardship Accounts Demo ===

[Maya] balance: $1000.00
[Maya] deposit $200.00 — balance: $1200.00
[Maya] give $150.00 to church — balance: $1050.00
[Maya] spend $40.00 on groceries — balance: $1010.00
Rejected: deposit must be positive. ($-50.00 declined.)
[Maya] balance: $1010.00

[Church Fund] balance: $0.00
[Church Fund] deposit $150.00 — balance: $150.00

(Your exact formatting can differ. The grader is looking for clarity, not template-matching.)

Note — The two-decimal dollars shown above ($1000.00) are a Hard-tier touch — getting that trailing-zero, always-two-decimals look takes <iomanip> (fixed + setprecision(2)), which is the H3 flex move, not a Chapter 9 tool. For Normal, plain numeric output like $1000 or $1010.5 is completely fine; don’t lose sleep over the cents formatting.

Normal-tier rubric (out of 100)

CriterionPoints
Compiles cleanly with -Wall -Wextra10
StewardshipAccount class declared with private balance/owner10
All 6 public methods present15
deposit rejects non-positive amounts10
give and spend reject negatives and overdrafts10
give and spend are distinct (not aliased to one)10
main exercises at least 10 ops across at least 2 accounts10
At least one rejected operation included in demo5
main does NOT access private fields directly10
OnlineGDB/GitHub link + reflection comment block10

Medium Tier (+up to 25% extra credit)

M1. Per-transaction log

Add a transaction log inside the class. The simplest implementation: a fixed-size array of strings plus a count.

private:
    string log[100];
    int log_count;

Every successful deposit, give, and spend appends a line like "DEPOSIT +$200.00" or "GIVE -$150.00 to church". (You can prompt for a “purpose” string at each operation if you want — that’s optional polish.) Modify print_statement() to print the full log under the current balance.

This is real encapsulation — the log lives inside the class, and outside code can only see it through print_statement().

M2. Linked savings account

Add a method void link_savings(StewardshipAccount& savings) that records a pointer (or reference) to a savings account. Then modify give and spend so that if either would overdraft, the class automatically pulls the needed amount from the linked savings account first, then completes the operation.

Coach’s Note — The “rainy day fund” pattern is prudent stewardship, not avarice. Christians historically have not been against saving — they’re against trusting savings, treating money as security in place of God. The class isn’t taking a position on that; it’s just letting you express the savings-account pattern when you want to.

Pointer-field preview (read before attempting). This Medium-tier feature uses a pointer field — a concept Chapter 11 covers formally. The five-line version:

class StewardshipAccount {
private:
    // ... other fields ...
    StewardshipAccount* linked;   // either nullptr or the address of another account
public:
    StewardshipAccount() : balance(0), linked(nullptr) { /* init others */ }
    void link_savings(StewardshipAccount& savings) { linked = &savings; }
    // ... and inside give/spend, check: if (linked != nullptr) { linked->give(...); }
};

Three rules: (1) linked is just an address; declare it StewardshipAccount* (note the asterisk). (2) Always initialize it to nullptr in your constructor — uninitialized pointers are worse than null. (3) Use -> instead of . when calling methods through it (linked->give(50), not linked.give(50)).

This is M2’s only chapter-11 dependency. The rest of the feature is plain stewardship logic.

If pointers feel premature, you can use a bool has_linked_savings flag plus a reference-storage hack, but the pointer is cleaner. Wait for Chapter 11 if you’d rather; this feature is Medium-tier extra credit, not required.

M3. Honesty mode

Add an optional bool honesty_mode flag (initialized to false). When true, every call to give or spend requires the caller to also pass a purpose string. The method records that purpose in the log. If honesty_mode is on and no purpose was given, reject the operation.

In main, run the demo once with honesty_mode = false and once with honesty_mode = true. Show how the log gets richer.

This isn’t a moral judgement — it’s just a small feature that demonstrates the class taking a stance on its own data discipline.


Hard Tier (+up to 25% additional extra credit)

H1. Compound interest

Add a method void compound_interest(double rate, int periods) that grows the balance over time:

for (int i = 0; i < periods; i++) {
    balance *= (1.0 + rate);
}

Log each period to the transaction log. Test with a 5% rate over 10 years on a $1000 balance — should grow to ~$1628.

H2. Audit method

Add void audit() that scans the transaction log for suspicious patterns — specifically, “three or more consecutive SPEND operations totaling more than 50% of the starting balance.” When detected, prints:

[AUDIT ALERT] You've spent $X in N consecutive transactions — that's M% of your starting balance.
You may be drifting from your plan. Worth a look.

This is not a moral pronouncement. It’s a diagnostic. The class is helping you see something you might have missed.

To implement, you’ll need to:

  1. Track the starting balance as a private field (double starting_balance).
  2. Parse the log entries (or, simpler: track a running count of consecutive spends and their sum, in private fields, updated as each transaction happens).

H3. The flex move

Find one C++ feature we haven’t covered. Strong candidates:

  • A const method qualifier: double get_balance() const { return balance; } — promises the method won’t modify the object. Necessary for calling methods on const Account& parameters.
  • <iomanip> and setprecision for clean dollar formatting.
  • An overloaded << operator so you can do cout << account instead of account.print_statement(). (This is a peek into operator overloading; will come back in Chapter 12.)

Document per Project 1 H4 rules.


Submission

Submit one URL via the course portal:

  • OnlineGDB project link (recommended for Coding 1 and Coding 2). Create your project at onlinegdb.com, set compiler flags to -Wall -Wextra in the project settings, build your solution, and share the link. See Appendix D for the full workflow.
  • GitHub repo link (optional). If you’ve set up local development on your own, push the source to a public repo and submit that URL. You’re responsible for making sure the code compiles when the grader checks it out.

What the linked project must contain

  1. The main source filestewardship.cpp — containing your full solution.
  2. A reflection comment block at the very top of that file:
/*
 * Tier targeted:    Normal / Medium / Hard
 * Features done:    list each feature you completed
 * What I learned:   one short paragraph (no bullets)
 * What I'd change:  one sentence
 * AI usage:         where and how, if any. Be honest.
 */
  1. The program left in a “demonstrable” state — when the grader presses Run, the features for your targeted tier should be exercised. Hard-code inputs at the top of main() (or pre-fill OnlineGDB’s Stdin panel) so the grader doesn’t have to guess what to type.

That’s it. No separate demo.txt. No screenshots. The instructor will open your link, read the comment block, run the program, and grade against the rubric.

Coach’s Note — Coding 1 and Coding 2 focus on writing code, not managing development environments. If something behaves oddly, you and the grader are looking at the exact same browser-hosted environment — there are no “works on my machine” defenses by design. Coding 3 will introduce a local toolchain properly.

Hints

  • “I want to print the balance from main.” Use get_balance(), not account.balance. The latter won’t compile — that’s encapsulation working.
  • “My give and spend look identical.” That’s correct for now. They have separate names so that, when you add the log in Medium tier, they appear differently. Don’t alias them by having one call the other — keep them distinct from the start.
  • “My linked savings auto-pull doesn’t work.” Make sure linked is a pointer (or reference). Storing a copy of an account won’t help — modifications to the copy don’t affect the original.
  • “The audit alert fires too eagerly.” Tune the threshold or the “consecutive” count. The point is the pattern detection, not perfect tuning.
  • “How long should this take me?” Normal: 3–5 hours. Medium: 5–8 hours. Hard: 8–14 hours.

What Mastery Looks Like

A great Project 9 has a class that truly enforces its rules. There’s no way for main to corrupt the account’s state. Every modification goes through a method. Every method has a guard. The grader could try every malicious input they can think of and the account would never end up in an impossible state.

A great Project 9 has main that uses the class without peeking inside it. main is a sequence of high-level operations: init, deposit, give, spend, print. The reader of main doesn’t need to know that balance is a double or that the log is an array — those are implementation details, hidden behind methods.

A great Project 9 takes the stewardship metaphor seriously without preaching. The class encodes some rules of careful financial stewardship — but it doesn’t tell you what to do with your money. It records what you did. The user is still in charge of the decisions. The class is the receipt.


When You’re Done

  1. Read your stewardship.cpp aloud. Each method does one thing. The names are verbs.
  2. Try, from main, to access balance directly. Confirm the compiler refuses.
  3. Run your demo. Trace the math. The final balance should be correct to the cent.
  4. Add/verify the reflection comment block at the top of stewardship.cpp. (Be honest about tier.) See the Submission section above and Appendix D.
  5. Submit.
  6. Read Chapter 10. Constructors fix the init() clunkiness.

Coach’s Note — This is the project that students often look back on as “the moment OOP clicked.” The shift from “data with rules I’ll remember to enforce” to “data with rules the class enforces for me” is genuinely a worldview shift. If it clicks here, the next four chapters become easier. If it hasn’t clicked yet, slow down and do every rep again. The shift is worth taking the time for.

See you on Monday.