⚡ TechVani: AI, Technology, Apps, Coding & Digital World
TechVaniAI • Technology • Apps • Coding • Digital World
HomeAI & TechAppsCodingFree AI ToolsStudent TechSecurityAboutContactPrivacy
TECHVANI // LEARN. BUILD. TEST.

Learn the tech. Build the idea.

Clear study notes, tested lab files and practical guides for coding, AI and digital safety.

Explore Latest →
šŸ¤– AI & TechAI news, tools & guides šŸ“± Apps & ToolsUseful apps & websites šŸ’» CodingProgramming & web development šŸŽ“ Student TechStudy & career technology šŸ” Cyber SecuritySafety & awareness

Latest Posts

Circuit Notebook theme

Exam Notes

šŸ“š BTech CSE Exam Notes

Find Semester 1-8 subjects in one place. Choose a semester and open the notes you need. This is a general study guide, not an official syllabus.

Open Exam Notes →🧪 Open Lab Files →

Exam Numericals & Study Series

Practice CPU scheduling and explore OS and DBMS topics in separate, easy-to-follow parts. New topics will appear in the hub as they are published.

Open Numericals Hub →

Start here and stay in touch

New to TechVani? Start with our free AI tools guide for students. It covers which tools to try and what to check before relying on an answer.

For step-by-step videos, visit SiteSudhar on YouTube.

Join TechVani on WhatsApp

Get new AI tools and coding guides in your WhatsApp Updates tab.

Browse Topics

Popular Posts

TechVani

Object-Oriented Programming using C++ | Semester 3 Core Notes

Semester 3 - Page 5: Object-Oriented Programming using C++. 32 numbered topics, highlighted rules, worked examples, answered exam questions, three diagrams and five complete C++17 programs. General common-core guide, not an official assessed syllabus or past-paper prediction. Compare your assigned outline and compiler version.

Run each whole block separately: g++ -std=c++17 -Wall -Wextra -pedantic demo.cpp -o demo, then ./demo. Inputs in main are fixed teaching examples. Book rejects negative copies. Square rejects negative/non-finite sides and sides above the square-root-of-max bound or whose computed square is non-finite. The Point demonstration requires coordinate sums to fit int; it is not an unchecked arbitrary-input arithmetic API. RAII traces show object lifetime, not a real file or device operation.

Topic map

  1. OOP goals and objects
  2. C++ compilation and versions
  3. Classes, structs and objects
  4. Access and encapsulation
  5. Constructors and initialization
  6. explicit and conversions
  7. Copy constructors and assignment
  8. Destructors and lifetime
  9. RAII and ownership
  10. Rule of zero, three and five
  11. Move semantics
  12. References, pointers and const
  13. this and member functions
  14. Static members and friends
  15. Composition and aggregation
  16. Public inheritance
  17. Multiple and virtual inheritance
  18. Overloading and name hiding
  19. Virtual functions and override
  20. Abstract classes and interfaces
  21. Virtual destructors and slicing
  22. Construction-time dispatch
  23. Operator overloading
  24. Templates and generic code
  25. Containers and iterators
  26. Exceptions and guarantees
  27. Smart pointers
  28. Streams and validation
  29. Files and resource scope
  30. Namespaces and separate definitions
  31. Design and test boundaries
  32. Revision and portability limits

1. OOP goals and objects

Object-oriented design groups state and behavior behind contracts. Encapsulation, abstraction, inheritance and polymorphism are related but distinct.

Worked example: A Book owns a copy count and exposes borrow rather than letting every caller decrement it.
Exam question: Is every program improved by inheritance?
Answer: No. Choose a design for its contracts and complexity, not a feature checklist.

2. C++ compilation and versions

Compile translation units, then link definitions. Standard mode and library support matter. These examples target C++17 and use standard headers, not bits/stdc++.h.

Worked example: g++ -std=c++17 -Wall -Wextra -pedantic demo.cpp -o demo, then ./demo.
Exam question: Can every compiler extension be assumed portable?
Answer: No. Use the selected language version and verify required library support.

3. Classes, structs and objects

A class describes a type; each object has a lifetime and state. class defaults to private members/inheritance, struct to public; both can have methods.

Worked example: Book b(2) creates one instance, not a second class definition.
Exam question: Is struct unable to use constructors or virtual functions?
Answer: No. It supports the same class mechanisms with different defaults.

4. Access and encapsulation

private limits access to class members/friends; protected also serves derived-class contexts; public is the client interface. Preserve invariants at every public boundary.

Worked example: Reject a negative starting copy count; refuse borrow when the count is zero.
Exam question: Does making fields private automatically validate them?
Answer: No. Constructors and methods must enforce the invariant.

5. Constructors and initialization

Constructors establish valid objects. Member initializers initialize directly; members are initialized in declaration order, not the written initializer-list order.

Worked example: Book(2) begins with two copies; Book(-1) throws before an invalid usable object is returned.
Exam question: Can a constructor have a return type?
Answer: No. It initializes the object rather than returning an ordinary function result.

Validated Book value and copying

#include <iostream>
#include <stdexcept>
class Book {
    int copies_;
public:
    explicit Book(int copies) : copies_(copies) {
        if (copies < 0) throw std::invalid_argument("negative copies");
    }
    bool borrow() {
        if (copies_ == 0) return false;
        --copies_; return true;
    }
    int available() const { return copies_; }
};
int main() {
    Book original(2), copy = original;
    std::cout << std::boolalpha;
    std::cout << copy.borrow() << ' ' << copy.borrow() << ' '
              << copy.borrow() << '\n';
    std::cout << "original: " << original.available()
              << "; copy: " << copy.available() << '\n';
    try { Book invalid(-1); }
    catch (const std::invalid_argument&) { std::cout << "negative rejected\n"; }
}

Checked output:

true true false
original: 2; copy: 0
negative rejected

6. explicit and conversions

explicit stops unintended implicit constructor conversion and selected conversion-function uses. Direct initialization can still call an explicit constructor.

Worked example: explicit Book(int) permits Book b(2), but not an implicit conversion from 2 to Book.
Exam question: Does explicit prohibit every construction?
Answer: No. It narrows conversion contexts.

7. Copy constructors and assignment

Copy construction creates a new object from another; copy assignment changes an existing object. Standard value members usually supply correct default copying.

Worked example: Book a(2); Book b=a copies two available copies; borrowing b does not alter a's integer member.
Exam question: Are copies always deep copies?
Answer: No. A raw pointer member normally copies its address, not the pointed-to object.

8. Destructors and lifetime

Destruction ends an object's lifetime and destroys owned members in reverse order. Automatic objects are destroyed at scope exit, including normal exception unwinding.

Worked example: A local vector releases its own storage when scope ends.
Exam question: Should you routinely call a local object's destructor manually?
Answer: No. It can cause later automatic destruction of an already-ended object.

9. RAII and ownership

Tie resource lifetime to an owning object's lifetime. Prefer standard containers and smart pointers to raw owning new/delete. Raw pointer syntax alone does not state ownership.

Worked example: A unique_ptr destroys its owned object when it leaves scope, including during unwinding.
Exam question: Does RAII mean every resource is a heap allocation?
Answer: No. Locks, file handles and other resources can have owners too.
Owner constructedUse resource within its lifetimeOwner destroyed: resource released
RAII ownership flow. Stack unwinding destroys completed local owners; the program trace checks reverse order.

RAII cleanup on exception path

#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>
struct Tracer {
    std::string name;
    explicit Tracer(std::string label) : name(std::move(label)) {
        std::cout << "acquire " << name << '\n';
    }
    ~Tracer() { std::cout << "release " << name << '\n'; }
};
int main() {
    try {
        auto first = std::make_unique<Tracer>("first");
        auto second = std::make_unique<Tracer>("second");
        throw std::runtime_error("demo failure");
    } catch (const std::runtime_error&) {
        std::cout << "handled\n";
    }
}

Checked output:

acquire first
acquire second
release second
release first
handled

10. Rule of zero, three and five

Prefer rule of zero with value/RAII members. A raw-owning-resource type needs deliberate copy/destruction behavior; C++11 move operations extend the usual rule-of-three discussion to five.

Worked example: A class containing string and vector often needs no custom destructor or copy operations.
Exam question: Should every class define all five special members?
Answer: No. Unnecessary custom members can inhibit useful implicit operations.

11. Move semantics

Move operations may transfer resources from expiring objects. std::move is a cast enabling overload selection, not a transfer by itself. Moved-from guarantees depend on the type.

Worked example: Moving a unique_ptr leaves the source empty and gives the destination ownership.
Exam question: Can every moved-from object be assumed empty?
Answer: No. Many standard-library objects are valid but have unspecified state; follow their documented guarantees.

Single-owner move and value composition

#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <utility>
struct Library { std::vector<std::string> titles; };
int main() {
    auto owner = std::make_unique<Library>();
    owner->titles = {"C++", "Algorithms"};
    auto destination = std::move(owner);
    std::cout << std::boolalpha << "source empty: " << !owner << '\n';
    std::cout << "destination titles: " << destination->titles.size() << '\n';
    Library copy = *destination;
    copy.titles.push_back("Math");
    std::cout << "original: " << destination->titles.size()
              << "; value copy: " << copy.titles.size() << '\n';
}

Checked output:

source empty: true
destination titles: 2
original: 2; value copy: 3

12. References, pointers and const

References alias objects; pointers may be null. const member functions cannot normally mutate non-mutable data through this. A const reference avoids a copy but does not extend every source lifetime.

Worked example: int available() const reads Book state; a pointer must be checked before dereferencing when null is possible.
Exam question: Does const imply thread safety?
Answer: No. External mutation, mutable members and shared resources still need synchronization.

13. this and member functions

this points to the current object in a non-static member function. Returning *this by reference supports chaining while preserving identity.

Worked example: An assignment-like method returning Book& can return *this.
Exam question: Does a static member function have this?
Answer: No. It has no implicit object.

14. Static members and friends

Static data belong to the class rather than each instance. Friends get specified private access; friendship is not automatically inherited, symmetric or transitive.

Worked example: An inline static C++17 counter can track live instances if all construction/destruction paths update it correctly.
Exam question: Are friend functions class members?
Answer: Not merely because they are declared as friends.

15. Composition and aggregation

Composition models an owned has-a relationship; aggregation is a looser lifetime relationship. State whether a member owns or merely observes another object.

Worked example: Library contains vector<Book>; an external catalog reference must outlive an observing Library.
Exam question: Is containment the same as inheritance?
Answer: No. Has-a and substitutable is-a express different contracts.
Library objectOwns vector of Book valuesEach Book preserves its invariant
Has-a composition: storage and child lifetimes are managed by owning members.

16. Public inheritance

Public inheritance should preserve base-type promises. Derived objects include base subobjects; access mode controls accessibility of inherited members, not whether base storage exists.

Worked example: Square can implement a Shape area contract; Library should not inherit Book simply to reuse fields.
Exam question: Do private base members disappear in a derived object?
Answer: No. They remain in its base subobject but are not directly accessible to derived code.

17. Multiple and virtual inheritance

Multiple inheritance adds several bases. A repeated common base may create ambiguity. Virtual inheritance shares one virtual base subobject; the most-derived constructor initializes it.

Worked example: A diamond D from B,C each virtually deriving A contains one shared A subobject.
Exam question: Does virtual inheritance mean every method is virtual?
Answer: No. Shared base layout and function dispatch are separate features.

18. Overloading and name hiding

Overloading selects among same-name functions with different parameter lists. Derived declarations can hide base overloads; using Base::name can reintroduce them.

Worked example: print(int) and print(double) overload; a return type alone cannot distinguish ordinary overloads.
Exam question: Is hiding automatically overriding?
Answer: No. Only the appropriate virtual signature overrides.

19. Virtual functions and override

A virtual call through a base pointer/reference can dispatch to the final overrider. override detects signature mistakes; final restricts further overriding/inheritance as applicable.

Worked example: Shape& bound to Square(3) returns area 9 from Square::area().
Exam question: Does adding const to only the derived method preserve the signature?
Answer: No. cv/ref qualifiers matter for overriding.
Shape pointer or referenceDynamic object: SquareSquare::area() returns 9
Runtime dispatch for a completed Square with side 3. Construction/destruction dispatch has separate rules.

Validated virtual dispatch and ownership

#include <iostream>
#include <memory>
#include <cmath>
#include <stdexcept>
#include <limits>
struct Shape {
    virtual double area() const = 0;
    virtual ~Shape() = default;
};
class Square final : public Shape {
    double side_;
public:
    explicit Square(double side) : side_(side) {
        if (!std::isfinite(side) || side < 0 ||
            side > std::sqrt(std::numeric_limits<double>::max()) ||
            !std::isfinite(side * side))
            throw std::invalid_argument("invalid side");
    }
    double area() const override { return side_ * side_; }
};
int main() {
    std::unique_ptr<Shape> shape = std::make_unique<Square>(3);
    std::cout << "area: " << shape->area() << '\n';
    Shape& reference = *shape;
    std::cout << "reference: " << reference.area() << '\n';
    try { Square invalid(-1); }
    catch (const std::invalid_argument&) { std::cout << "negative rejected\n"; }
}

Checked output:

area: 9
reference: 9
negative rejected

20. Abstract classes and interfaces

A pure virtual function makes a class abstract until the required final overriders are supplied. Pure virtual destructors still need a definition if used.

Worked example: virtual double area() const=0 makes Shape abstract; a concrete Square implements it.
Exam question: Can you create an ordinary object of an abstract class?
Answer: No. Pointers and references to it are permitted.

21. Virtual destructors and slicing

Delete through a polymorphic base pointer only with the correct destruction contract, normally a public virtual destructor. Copying a derived value into a base value slices its derived portion.

Worked example: unique_ptr<Shape> holding Square cleans up through Shape's virtual destructor.
Exam question: Is a base value a substitute for a base reference in polymorphic storage?
Answer: Not generally. Value copying can slice; use a deliberate ownership/reference design.

22. Construction-time dispatch

During base construction/destruction, virtual dispatch does not reach a more-derived part whose lifetime is not active. Avoid calling pure virtual functions on that path.

Worked example: A Base constructor calling a virtual method uses Base's active implementation, not Derived's later one.
Exam question: Can override force derived dispatch from a base constructor?
Answer: No. Lifetime-stage rules still apply.

23. Operator overloading

Operators can express natural value operations but cannot invent new precedence or overload every operator. Keep algebraic expectations clear and avoid surprising side effects.

Worked example: A two-integer Point plus Point adds corresponding coordinates within the stated safe range.
Exam question: Can operator+ change its precedence relative to multiplication?
Answer: No. Parsing rules remain fixed.

Point operator and template value selection

#include <iostream>
#include <string>
struct Point { int x, y; };
/* Demo contract: coordinate sums fit int. */
Point operator+(Point a, Point b) { return {a.x + b.x, a.y + b.y}; }
template<class T>
T maximum(T a, T b) { return a < b ? b : a; }
int main() {
    Point p = Point{2, 3} + Point{4, -1};
    std::cout << "point: " << p.x << ',' << p.y << '\n';
    std::cout << "max int: " << maximum(4, 7) << '\n';
    std::cout << "max text: " << maximum(std::string("cat"), std::string("car")) << '\n';
}

Checked output:

point: 6,2
max int: 7
max text: cat

24. Templates and generic code

Templates parameterize types/values; operations in the implementation constrain supported types. Instantiation errors can expose an unmet requirement.

Worked example: maximum<T> requires a meaningful less-than comparison; a tie can deliberately return the first input.
Exam question: Does a template work for every imaginable type?
Answer: No. The body must be valid for the chosen arguments.

25. Containers and iterators

vector owns contiguous elements; string owns text. Iterators denote positions and have container-specific invalidation rules. Avoid retaining a vector pointer across reallocation.

Worked example: After push_back triggers a vector reallocation, prior element references/iterators may be invalid.
Exam question: Does reserve make every later iterator safe forever?
Answer: No. Exceeding capacity or other operations can invalidate them.

26. Exceptions and guarantees

Throw reports failure to a handler; catch by const reference for typical standard exceptions. RAII releases owners during stack unwinding. Basic, strong and no-throw guarantees differ.

Worked example: An invalid Book argument throws invalid_argument; a surrounding handler can report rejection.
Exam question: Does catching every exception make a program correct?
Answer: No. Preserve state invariants and handle only where a useful recovery exists.

27. Smart pointers

unique_ptr is single ownership and non-copyable. shared_ptr shares ownership; weak_ptr observes without adding strong ownership. Avoid strong reference cycles.

Worked example: A owns B and B owns A through shared_ptr can keep both alive; an observing weak_ptr can break the cycle.
Exam question: Does shared_ptr make the pointed-to data thread-safe?
Answer: No. Ownership-count safety is not shared-object synchronization.

28. Streams and validation

Formatted extraction sets stream state on failure. Check extraction and validate ranges separately. For strict whole-line numeric input, reject trailing junk deliberately.

Worked example: Parsing 40abc as an integer may read 40 then leave abc; choose whether that violates the input contract.
Exam question: Can good-looking output prove a failed input was accepted correctly?
Answer: No. Inspect stream state and validation results.

29. Files and resource scope

Use RAII file streams and check opening, read/write and close/flush status appropriate to the task. Do not overwrite personal files for examples.

Worked example: A practice file stream releases its handle at scope exit; successful buffered output is not an unconditional durability promise.
Exam question: Does closing always prove permanent storage against power failure?
Answer: No. Durability guarantees depend on the platform and storage protocol.

30. Namespaces and separate definitions

Namespaces organize names; declarations and definitions have different roles. One-definition-rule constraints govern how entities appear across translation units.

Worked example: Declare a class interface in a header, define non-inline methods in an implementation file and link it once.
Exam question: Should every header contain unrestricted global using namespace std?
Answer: No. It can pollute clients' lookup and create collisions.

31. Design and test boundaries

Prefer small contracts, composition and clear ownership. Test normal, boundary, invalid and polymorphic behavior; compile warnings help but are not a proof.

Worked example: Book with zero copies refuses borrow; negative copies reject; Square validates finite nonnegative side.
Exam question: Is a passing demo proof of every input path?
Answer: No. Use tests and reasoning matched to the contract.

32. Revision and portability limits

State the C++ version, ownership, lifetime and preconditions before explaining a trace. These are common-core notes, not a college-syllabus certification.

Worked example: Class private default; struct public default; overload compile-time selection; virtual override runtime dispatch; has-a composition.
Exam question: What should a program answer include?
Answer: Complete source, build command, checked output, validation policy and limitations.

Concept comparison

ConceptMeaningCommon mistake
OverloadSame name, different parametersReturn type alone does not distinguish ordinary overloads
OverrideDerived implementation of virtual signatureMissing const/ref qualifier changes signature
CompositionOwn/use another objectHas-a is not inheritance
Public inheritanceSubstitutable base contractCode reuse alone is insufficient
RAIIOwnership follows object lifetimeRaw pointers do not state ownership
unique_ptrSingle ownerCannot copy ownership
shared_ptrShared ownershipDoes not synchronize object data
constRestricted modification through this accessDoes not guarantee thread safety

Checked trace reference

ExampleResultContract
Book copy borrows three timestrue,true,false; original2,copy0Initial2, value copying
Square through Shape9Finite side3, virtual method/destructor
RAII exception cleanupsecond then first, then handledCompleted local owners unwind
Point2,3 plus4,-16,2Sums fit int
maximum4,77Comparable int values
unique_ptr movesourceempty, destination2titlesUnique ownership guarantee
Value Library copyoriginal2,copy3titlesvector/string value members

Revision checklist

  1. Explain valid state and access boundaries.
  2. Trace initialization, copy/move and destruction.
  3. State ownership and lifetime of every pointer/reference.
  4. Separate overload, override, hiding and slicing.
  5. Use composition or substitutable inheritance deliberately.
  6. Test invalid inputs and exception cleanup as well as happy paths.
  7. Check version, iterator validity and numeric preconditions.

Practice resources

Continue with the C++ OOP Lab File, Lab Files index and Online Compiler: choose C++.

Sources

Language/reference pages support the rules; explanations, diagrams and complete programs here are original teaching material. Later-version features shown by a reference are not required by these C++17 examples.

Comments