Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

C++ Object-Oriented Programming Fundamentals: Inheritance and Constructors

Tech May 13 1

Experiment Objectives

  1. Understand the relationship between classes and objects, master constructors and destructors, and implement encapsulation
  2. Learn how to define base and derived classes, and understand the calling order of constructors and destructors
  3. Master the principles and methods of multiple inheritance and virtual inheritance
  4. Review function overloading (member and friend functions) and common operator overloading

Experiment Content

Exercise 1: Basic Class Inheritance

Compile and run the following program, then explain the purpose of each statement:


#include <iostream>
using namespace std;

class BaseClass {  // Define a base class named BaseClass
public:  // Public access specifier
    BaseClass() {cout << "Base class constructor called" << endl;}  // Base class constructor
    ~BaseClass() {cout << "Base class destructor called" << endl;}  // Base class destructor
};

class DerivedClass : public BaseClass {  // Define derived class DerivedClass with public inheritance
public:  // Public access specifier
    DerivedClass() {cout << "Derived class constructor called" << endl;}  // Derived class constructor
    ~DerivedClass() {cout << "Derived class destructor called" << endl;}  // Derived class destructor
};

int main() {
    DerivedClass obj;  // Create an object of DerivedClass
    return 0;
}
</iostream>

Output Result


Base class constructor called
Derived class constructor called
Derived class destructor called
Base class destructor called

Exercise 2: Constructor Initialization with Member Objects

Compile and run the following program, then explain the purpose of each statement:


#include <iostream>
using namespace std;

class BaseClass {  // Define base class BaseClass
private:  // Private access specifier
    int value;  // Private member variable value
public:  // Public access specifier
    BaseClass(int a) {  // Base class parameterized constructor
        cout << "Base class constructor called" << endl;
        value = a;  // Assign parameter a to member variable value
        cout << "value = " << value << endl;
    }
    ~BaseClass() {cout << "Base class destructor called" << endl;}  // Base class destructor
};

class DerivedClass : public BaseClass {  // DerivedClass publicly inherits BaseClass
    BaseClass memberObj;  // Member object: object of BaseClass
    int derivedValue;  // Private member variable in derived class
public:  // Public access specifier
    DerivedClass(int a, int b, int c) : BaseClass(a), memberObj(c) {  // Initialize base class and member object
        cout << "Derived class constructor called" << endl;
        derivedValue = b;  // Assign parameter b to member variable derivedValue
        cout << "derivedValue = " << derivedValue << endl;
    }
    ~DerivedClass() {cout << "Derived class destructor called" << endl;}  // Derived class destructor
};

int main() {
    DerivedClass obj(1, 2, 3);  // Create DerivedClass object obj with parameters 1, 2, 3
    return 0;
}
</iostream>

Output Result


Base class constructor called
value = 1
Base class constructor called
value = 3
Derived class constructor called
derivedValue = 2
Derived class destructor called
Base class destructor called
Base class destructor called

Exercise 3: Multiple Inheritance

Compile and run the following program, then explain the purpose of each statement:


#include <iostream>
using namespace std;

class A {  // Define base class A
public:  // Public access specifier
    int n;  // Public member variable n
};

class B : public A {};  // Class B publicly inherits A
class C : public A {};  // Class C publicly inherits A
class D : public B, public C {  // Class D inherits from both B and C
public:
    int getValue() { return B::n; }  // Member function to return n inherited from B
};

int main() {
    D d;  // Create D class object d
    d.B::n = 10;  // Access and set n through B path to 10
    d.C::n = 20;  // Access and set n through C path to 20
    cout << d.B::n << "," << d.C::n << endl;  // Output both n values
    return 0;
}
</iostream>

Output Result

10,20

Thought Question

Run the following program and explain the differences from the previous example:


#include <iostream>
using namespace std;

class A {
public:
    int n;
};

class B : virtual public A {};  // Virtual inheritance
class C : virtual public A {};  // Virtual inheritance
class D : public B, public C {
public:
    int getValue() { return B::n; }
};

int main() {
    D d;
    d.B::n = 10;
    d.C::n = 20;
    cout << d.B::n << "," << d.C::n << endl;
    return 0;
}
</iostream>

Difference

This example uses virtual inheritance, unlike the previous one. The output is different because in the previous example, B::n and C::n were two different variables, so they could have different values (10 and 20). Here, B::n and C::n point to the same location, so they represent the same variable, which ends up being 20 (the last value assigned).

Output Result

20,20

Exercise 4: Shape Classes with Area Calculation

Define a Point class and derive Rectangle and Circle classes from it, implementing an Area() function for each derived class:


#include <iostream>
#include <cmath>
using namespace std;

class Point {
protected:
    int x, y;
public:
    Point(int xx = 0, int yy = 0) : x(xx), y(yy) {}
    void display() const {cout << "(" << x << "," << y << ")";}
    int getX() const {return x;}
    int getY() const {return y;}
};

class Rectangle : public Point {
private:
    int width, height;
public:
    Rectangle(int x = 0, int y = 0, int w = 0, int h = 0) : Point(x, y), width(w), height(h) {}
    double Area() const {
        return width * height;
    }
    void display() const {
        Point::display();
        cout << ", Rectangle width: " << width << ", Rectangle height: " << height;
        cout << ", Rectangle area: " << Area() << endl;
    }
};

class Circle : public Point {
private:
    int radius;
public:
    Circle(int x = 0, int y = 0, int r = 0) : Point(x, y), radius(r) {}
    double Area() const {
        return 3.14 * radius * radius;
    }
    void display() const {
        Point::display();
        cout << ", Circle radius: " << radius;
        cout << ", Circle area: " << Area() << endl;
    }
};

int main() {
    Rectangle rect(1, 1, 4, 3);
    rect.display();
    Circle circ(2, 2, 2);
    circ.display();
    return 0;
}
</cmath></iostream>

Output Result


(1,1), Rectangle width: 4, Rectangle height: 3, Rectangle area: 12
(2,2), Circle radius: 2, Circle area: 12.56

Experiment Summary

Through multiple examples of constructors and destructors, we've mastered the construction order for derived classes containing member objects (base class → member objects → derived class). Through a comparative experiment between regular inheritance and virtual inheritance, we've understood the principles of virtual inheritance. We've also understood the differences between member functon and friend function overloading and how to choose between them, as well as why certain operators must be implemented as friend functions.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.