Saturday, April 19, 2025

C++ OO Virtual Inheritance, Diamond Problem

Virtual inheritance is a mechanism in C++ that allows a derived class to inherit from a base class such that only one instance of the inherited class is present in the memory, even if multiple paths exist in the inheritance hierarchy.

In a regular inheritance relationship, when a derived class inherits from a base class, a new instance of the base class is created for each derived class. However, in some cases, this can lead to ambiguity, for example, when a class inherits from multiple base classes that themselves have a common base class. Virtual inheritance solves this problem by creating a single shared base class subobject. 


	A

B		C

	D

The diamond problem is a common problem that arises in C++ when multiple inheritance is used with virtual inheritance. It occurs when a class inherits from two classes that have a common base class. The result is that the derived class has two copies of the common base class, leading to ambiguities in the code.

For example, consider the following class hierarchy:

 
      Animal
     /      \
   Dog    Cat
     \      /
      Pet

 

Here, Dog and Cat inherit from Animal, and Pet inherits from both Dog and Cat. If Pet were to call a method inherited from Animal, there would be two copies of that method available: one from Dog and one from Cat. This ambiguity can lead to errors and is known as the diamond problem.

To solve the diamond problem, virtual inheritance is used. Virtual inheritance allows a class to inherit from a base class only once, even if it appears multiple times in the class hierarchy. In the example above, Pet would inherit virtually from Animal, resulting in only one copy of the Animal class in the Pet class hierarchy. This ensures that there are no ambiguities when calling methods inherited from the common base class. 


#include <iostream>

using namespace std;

class Prim_A{
    public:
        void printStuff() {
            cout << "I am from A Class" << endl;
        }
};

class Sec_B : virtual public Prim_A{

};

class Sec_C : virtual public Prim_A{

};

class Ter_D : public Sec_B, public Sec_C{

};

int main() {

    Ter_D Object;
    Object.printStuff();

    return 0;
}

This code demonstrates the concept of virtual inheritance in C++.

In this example, there are three classes: Prim_A, Sec_B, and Sec_C, and a derived class Ter_D. The Prim_A class has a method printStuff(), which simply outputs a message to the console.

Both Sec_B and Sec_C inherit from Prim_A using virtual inheritance. This means that when the Ter_D class inherits from both Sec_B and Sec_C, there will be only one instance of Prim_A shared by both Sec_B and Sec_C.

This avoids the diamond problem and ensures that there is only one copy of the Prim_A base class in Ter_D. The main() function creates an object of Ter_D class and calls the printStuff() method which is inherited from Prim_A through virtual inheritance.

C++ OO Abstract Classes

The purpose of an abstract class is to define a common interface for a set of related classes.

The derived classes must implement the pure virtual function(s) of the abstract class in order to be instantiated.

This way, an abstract class can provide a common functionality that all the derived classes must have, while allowing each derived class to implement its own specific behavior. 


#include <iostream>

using namespace std;

class Prim{
    public:
        virtual void printing() {}
};

class Sec : public Prim{
    public:
        void printing() {
            cout << "I am From Sec Cls" << endl;
        }
};

class Third : public Prim {
    public:
        void printing() {
            cout << "I am from Third Cls" << endl;
        }
};

int main() {

    Prim Object;
    Object.printing();

    return 0;
}

In this C++ code, we have defined a class hierarchy with a base class Prim and two derived classes Sec and Third. The base class Prim has a virtual function printing(), which is overridden in both derived classes.

In the main() function, an object of the base class Prim is created and its printing() function is called. Since the printing() function is virtual and has been defined in the base class with an empty definition, it will call the base class's implementation. Therefore, the output will be an empty line.

Note that the Prim class is an abstract class, as its virtual function printing() has an empty definition, and hence it cannot be instantiated. We can only create objects of the derived classes, which have overridden the virtual function.

C++ OO Pure Virtual Functions

A pure virtual function is a virtual function that has no implementation in the base class and must be overridden by any derived classes that inherit from the base class.  

Pure virtual functions are useful when you have a base class that defines a common interface, but the implementation of the function is left to the derived classes. By making the function pure virtual, you require the derived classes to implement the function and provide their own implementation.

Pure virtual functions are commonly used in abstract base classes, which are classes that are not meant to be instantiated directly, but are designed to be subclassed by other classes that provide the implementation of the pure virtual functions.


#include <iostream>

using namespace std;

class Prim{
    public:
        virtual void printing()=0;
};

class Sec : public Prim{
    public:
        void printing() {
            cout << "I am From Sec Cls" << endl;
        }
};

class Third : public Prim {
    public:
        void printing() {
            cout << "I am from Third Cls" << endl;
        }
};

int main() {

    Third Object;
    Object.printing();

    return 0;
}

This C++ program demonstrates the use of a pure virtual function in a class hierarchy.

In this example, the class Prim contains a pure virtual function called printing(). A pure virtual function is declared with the syntax virtual void functionName() = 0; and has no implementation.

Since Prim contains a pure virtual function, it is an abstract class and cannot be instantiated. The classes Sec and Third inherit from Prim and implement the printing() function in their own unique ways.

In the main() function, an object of the Third class is created and its printing() function is called, which outputs the message "I am from Third Cls" to the console.

The use of pure virtual functions allows for polymorphism in C++. By creating a pure virtual function in a base class, we can ensure that all derived classes provide their own implementation of that function.

C++ OO Pointers in Polymorphism

Pointers are often used in C++ to achieve polymorphism. When a function is declared as virtual, it enables dynamic binding, which means that the appropriate function to call is determined at runtime based on the type of the object pointed to by the pointer.

In other words, when a pointer of the base class type points to an object of the derived class, and the function is called using the pointer, the function in the derived class is executed rather than the function in the base class. This is an important aspect of polymorphism in C++, and it allows for the creation of flexible and extensible code. 


#include <iostream>

using namespace std;

class Prim{
    public:
        virtual void printing() {}
};

class Sec : public Prim{
    public:
        void printing() {
            cout << "I am From Sec Cls" << endl;
        }
};

class Third : public Prim {
    public:
        void printing() {
            cout << "I am from Third Cls" << endl;
        }
};

int main() {

    Sec Object;
    Sec *Ptr1 = &Object;

    Ptr1->printing();

    Third Object_2;
    Third *Ptr2 = &Object_2;

    Ptr2->printing();

    return 0;
}

This C++ code defines three classes: Prim, Sec, and Third. The Prim class has a virtual function printing() defined. The Sec and Third classes inherit from Prim and override the printing() function.

In the main() function, an object of the Sec class is created and a pointer Ptr1 of type Sec is initialized to point to the Object object. The Ptr1->printing() statement calls the printing() function on the object pointed to by Ptr1. Since the printing() function is virtual and has been overridden in the Sec class, the printing() function in the Sec class is called and the output is "I am From Sec Cls".

Then, an object of the Third class is created and a pointer Ptr2 of type Third is initialized to point to the Object_2 object. The Ptr2->printing() statement calls the printing() function on the object pointed to by Ptr2. Again, since the printing() function is virtual and has been overridden in the Third class, the printing() function in the Third class is called and the output is "I am from Third Cls".

C++ OO Polymorphism, Virtual Functions

Polymorphism in C++ is the ability of objects of different classes to be treated as if they are objects of the same class. In C++, polymorphism can be achieved through inheritance and virtual functions.

Polymorphism through inheritance is achieved by creating a derived class that inherits from a base class. The derived class can override the methods of the base class with its own implementation, and objects of the derived class can be treated as objects of the base class.

Polymorphism through virtual functions is achieved by declaring a function in the base class as virtual, which allows derived classes to provide their own implementation of the function. When a virtual function is called on an object, the appropriate implementation of the function is selected based on the type of the object at runtime, rather than the type of the variable used to refer to the object.

Polymorphism allows for more flexible and reusable code, as objects of different classes that share a common base class can be treated in the same way. This can simplify program design and make code easier to maintain and extend.

A virtual function is a function that is declared in a base class and can be overridden in a derived class. When a virtual function is called on an object, the appropriate implementation of the function is selected based on the type of the object at runtime, rather than the type of the variable used to refer to the object.

To declare a virtual function, the virtual keyword is used before the function declaration in the base class. 


#include <iostream>

using namespace std;

class Prim{
    public:
        virtual void printing() {}
};

class Sec : public Prim{
    public:
        void printing() {
            cout << "I am From Sec Cls" << endl;
        }
};

class Third : public Prim {
    public:
        void printing() {
            cout << "I am from Third Cls" << endl;
        }
};

int main() {

    Sec Object;
    Object.printing();

    Third Object_2;
    Object_2.printing();

    return 0;
}

This C++ code defines three classes: Prim, Sec, and Third. Prim is the base class, and Sec and Third are derived classes that inherit from Prim. The Prim class has a virtual function called printing() that does not have any implementation, and Sec and Third both override the printing() function with their own implementations.

In the main() function, two objects are created, one of type Sec and one of type Third, and their printing() methods are called. Since the printing() method is declared as virtual in the base class Prim, the appropriate implementation of the function is selected based on the type of the object at runtime.

C++ OO Objects As Parameters

We can pass objects as parameters to functions. When an object is passed as a parameter to a function, a copy of the object is created and passed to the function. This copy is then used within the function and any modifications made to the object will not affect the original object passed as the argument. 


#include <iostream>

using namespace std;

class Prim{
    public:
        void printMe() {
            cout << "From Prim Cls" << endl;
        }
};

class Sec : public Prim{
    public:
        void printMe() {
            cout << "From Sec Cls" << endl;
        }
};

void caller(Prim x) {
    x.printMe();
}

int main() {

    Sec Object;
    caller(Object);

    return 0;
}

Ours C++ code defines two classes, Prim and Sec, where Sec is a derived class of Prim.

Prim has a public member function called printMe() that simply outputs a message saying "From Prim Cls". Sec also has a public member function called printMe(), but it overrides the implementation of printMe() in the Prim class and outputs a different message, saying "From Sec Cls".

The code also defines a function called caller() that takes an object of type Prim as a parameter and calls its printMe() method.

In the main() function, an instance of Sec called Object is created, and the caller() function is called with Object as an argument. Since Sec is a subclass of Prim, an instance of Sec can be treated as an instance of Prim.

However, since the caller() function takes an object of type Prim as a parameter, the printMe() method of the Prim class is called, not the printMe() method of the Sec class. 


#include <iostream>

using namespace std;

class Prim{
    public:
        void printMe() {
            cout << "From Prim Cls" << endl;
        }
};

class Sec : public Prim{
    public:
        void printMe() {
            cout << "From Sec Cls" << endl;
        }
};

class Third : public Sec{
    public:
        void printMe() {
            cout << "From Third Cls" << endl;
        }
};

void caller(Prim x) {
    x.printMe();
}

void callerT(Sec y) {
    y.printMe();
}

int main() {

    Third Object;
    callerT(Object);

    return 0;
}

This C++ code defines three classes, Prim, Sec, and Third, where Sec is a derived class of Prim and Third is a derived class of Sec.

Prim has a public member function called printMe() that outputs a message saying "From Prim Cls". Sec also has a public member function called printMe(), but it overrides the implementation of printMe() in the Prim class and outputs a different message, saying "From Sec Cls". Third also has a public member function called printMe(), but it overrides the implementation of printMe() in both the Prim and Sec classes and outputs a different message, saying "From Third Cls".

The code defines two functions called caller() and callerT(), each of which takes an object of a different class as a parameter and calls its printMe() method.

In the main() function, an instance of Third called Object is created, and the callerT() function is called with Object as an argument. Since Object is an instance of Third, it can be treated as an instance of both Sec and Prim, so the printMe() method of Sec is called.

C++ OO This Pointer

this is a keyword that represents a pointer to the current object instance. It is a special pointer that is automatically created and initialized by the compiler for each member function of a class.

When a member function is called on an object, the this pointer points to the memory address of that object. The this pointer can be used to access member variables and member functions of the current object, as well as to return a reference to the current object.

#include <iostream>
using namespace std;

class First{
    private:
        string name;

    public:
        void setName(string x) {
            this->name = x;
        }

        void getName() {
            cout << "Name: " << name << endl;
        }
};

int main() {

    First Object;
    Object.setName("Slavoj Zizek");
    Object.getName();

    return 0;
}

this is a keyword that refers to the current object. The this keyword is used to disambiguate between the local parameter variable name and the class data member name.

In the setName function, this->name refers to the name data member of the current object. This is used to set the value of the name data member of the current object to the value passed to the function as the parameter.

In this way, this helps to differentiate between the local variable name and the class member name which have the same name.

C++ OO Accessing Overloaded Methods

This code demonstrates how to use scope resolution operator to access a method that is overloaded in multiple classes in a hierarchy: 


#include <iostream>

using namespace std;

class Prim{
    public:
        void sameName() {
            cout << "I am from Prim Cls" << endl;
        }
};

class Sec : public Prim{
    public:
        void sameName() {
            cout << "I am from Sec Cls" << endl;
        }
};

class Third : public Sec{
    public:
        void sameName() {
            cout << "I am from Third Cls" << endl;
        }
};

int main() {

    Sec Object;
    Object.Prim :: sameName();

    Third Object_T;
    Object_T.Sec :: sameName();

    return 0;
}

The code defines three classes: Prim, Sec, and Third. Sec is derived from Prim, and Third is derived from Sec. All three classes have a method named sameName(), which is overloaded in each derived class.

In the main() function, two objects are created, one of Sec and one of Third. The scope resolution operator :: is used to access the sameName() method of the base class Prim of Sec object and the sameName() method of the base class Sec of Third object.

When Object.Prim :: sameName() is called, it calls the sameName() method of Prim class because it is explicitly qualified with the name of the class. Similarly, Object_T.Sec :: sameName() calls the sameName() method of the Sec class.

C++ OO Method Overloading

Method overloading in C++ is a feature that allows a class to have multiple member functions with the same name but with different parameters.

When a function is called, the compiler matches the parameters provided with the appropriate function based on the number, type, and order of the parameters. 


#include <iostream>

using namespace std;

class Prim{
    public:
        void sameName() {
            cout << "I am from Prim Cls" << endl;
        }
};

class Sec : public Prim{
    public:
        void sameName() {
            cout << "I am from Sec Cls" << endl;
        }
};

int main() {

    Sec Object;
    Object.sameName();

    Prim Obj_2;
    Obj_2.sameName();

    return 0;
}

In this example, we have two classes, Prim and Sec, and both have a method with the same name sameName(). However, the implementation of the method is different in both classes.

In Sec, the sameName() method prints "I am from Sec Cls", and in Prim, the sameName() method prints "I am from Prim Cls".

When we create an object of Sec and call the sameName() method, the implementation in the Sec class is executed, and "I am from Sec Cls" is printed. When we create an object of Prim and call the sameName() method, the implementation in the Prim class is executed, and "I am from Prim Cls" is printed.

This is because the compiler distinguishes between the two methods based on their signature, which includes the method name and the types and number of parameters. When there are multiple methods with the same name but different signatures, the compiler decides which method to call based on the arguments passed to it. This is called method overloading.

C++ OO Constructor Calling Constructor

Constructor calling constructor is useful when a derived class needs to initialize its base class members before initializing its own members. In some cases, it can make the code more concise and easier to read. 


#include <iostream>

using namespace std;

class Prim{
    public:
        string name;

        Prim(string x) {
            name = x;
        }
};

class Sec : public Prim{
    public:
        Sec(string y) : Prim(y) {
            cout << "Done" << endl;
        }

        void printAll() {
            cout << name << endl;
        }
};

int main() {

    Sec Obj("Michael");
    Obj.printAll();

    return 0;
}

A constructor in C++ can call another constructor using a technique called constructor chaining or constructor delegation.

In the code you provided, the constructor of the Sec class is calling the constructor of the Prim class using the syntax : Prim(y) in the constructor initialization list. This means that before executing the body of the Sec constructor, the constructor of the Prim class is called first with the argument y. This initializes the name member variable of the Prim class with the value of y.

Then, the body of the Sec constructor executes, which simply outputs "Done" to the console. Finally, the printAll() function is called on the Obj object, which prints the value of the name member variable inherited from the Prim class.

C++ OO Multiple Inheritance

Multiple inheritance is a feature in C++ that allows a class to inherit from more than one base class. This means that the derived class can have access to all the members of the base classes that it inherits from.

The need for multiple inheritance arises when a derived class needs to inherit functionality from more than one base class. For example, suppose you want to create a class that represents a square shape in both two-dimensional and three-dimensional space. You could have a base class for two-dimensional shapes and another base class for three-dimensional shapes. By using multiple inheritance, you can create a derived class that inherits from both of these base classes and has access to the functionality of both.

Multiple inheritance can also be used to create a hierarchy of classes with different levels of specialization. 


#include <iostream>

using namespace std;

class First{
    public:
        string name = "Jordan";

        void printName() {
            cout << "Name: " << name  << endl;
        }
};

class Second{
    public:
        string last_name = "Peterson";

        void printLastName() {
            cout << "Last Name: " << last_name << endl;
        }

};

class Third : public First, Second {
    public:
        void caller() {
            printName();
            printLastName();
        }
};

int main() {

    Third Object;
    Object.caller();

    return 0;
}

In this code, the classes First and Second are being inherited publicly by the class Third, which means that the public and protected members of First and Second will be accessible by the objects of Third.

Third class has a member function caller() which calls the member functions of both the base classes, First and Second. The printName() and printLastName() functions of the First and Second classes respectively are being called using the object of the Third class. 


int main() {

    Third Object;
    Object.caller();

    First Obj_1;
    Obj_1.printName();

    Second Obj_2;
    Obj_2.printLastName();

    return 0;
}

We have created three objects of three different classes.

The first object Object is of the class Third, which inherits from both First and Second classes. Object calls the caller function, which in turn calls printName function from First class and printLastName function from Second class. Therefore, when Object.caller() is executed, it prints out both the name and the last name.

The second object Obj_1 is of the class First, and we call the printName function of First class, which simply prints out the name variable.

The third object Obj_2 is of the class Second, and we call the printLastName function of Second class, which simply prints out the last_name variable.

So, in summary, we are able to create objects of different classes and call their respective member functions, and in case of Third class object, it is able to call member functions of both First and Second classes because it inherits from both of them.

C++ OO Changing Access Levels

C++ OO Private Inheritance

Private inheritance is one of the three types of inheritance that allows a derived class to inherit the properties of a base class. With private inheritance, all public and protected members of the base class become private members of the derived class. This means that the derived class can access the inherited members, but they are not visible to any external code. 

#include <iostream>

using namespace std;

class Prim{
    protected:
        string name;

    public:
        void setName(string x) {
            name = x;
        }
};

class Sec : private Prim{
    public:
        void printName() {
            cout << "Name from Prim Cls: " << name << endl;
        }

        void caller(string x) {
            setName(x);
        }
};

int main() {

    Sec Object;
    Object.caller("Anabela");
    Object.printName();

    return 0;
}

The class Sec inherits from the class Prim using private inheritance. This means that Sec is a derived class of Prim, but it can only access the protected and public members of Prim through its own interface.

In other words, Sec can access the setName function of Prim, which is public, and can set the value of name, which is protected. However, it cannot access name directly, as it is private in Sec.

The printName function in Sec is able to print the value of name by calling it through the setName function which is public in Prim.

In the main function, an object of Sec is created and the caller function is called to set the value of name to "Anabela". The printName function is then called to print the value of name, which is "Anabela" in this case.

C++ OO Protected Inheritance

Protected inheritance is useful when you want to derive a new class from an existing base class, but you don't want to expose all of the members of the base class to the derived class or to the outside world.

For example, consider a class hierarchy for different types of shapes. The base class may have a protected member variable for the color of the shape, as well as public member functions for getting and setting the color. A derived class for circles may want to inherit this color functionality, but it may not want to expose the color to the outside world as a public member.

In this case, the derived class could use protected inheritance to inherit the color functionality from the base class, while keeping the color variable itself protected. This way, the derived class can still use the color variable internally, but it's not exposed to code outside of the class hierarchy.

Another example is a base class for a widget in a graphical user interface. The base class may have protected member variables for the size and position of the widget, as well as public member functions for getting and setting these values. A derived class for a button may want to inherit these size and position members, but it may not want to expose them as public members to the outside world. Protected inheritance can be used in this case to inherit the size and position functionality while keeping the actual variables protected.

In general, protected inheritance is useful when you want to inherit some of the functionality of a base class without exposing all of its members to the derived class or to code outside of the class hierarchy.

People can sometimes confuse the concepts of protected, public, and private in C++ because they all deal with the visibility of data and functions in a class hierarchy, and their use can be somewhat subjective depending on the specific design goals and requirements of a program.

Additionally, the syntax used in C++ to denote the different access levels can be a bit confusing, particularly for beginners. For example, it may not be immediately clear what the difference is between protected and private, or why one would use public inheritance instead of private inheritance.

Another reason for confusion is that the access level of a member function or data member can have a cascading effect on the accessibility of other members in the class hierarchy. For example, if a member function is marked as protected, then any derived classes can access that function as well, even if they are not marked as protected. This can make it difficult to reason about the accessibility of members in complex class hierarchies.

Finally, some programmers may not fully understand the implications of using different access levels, or may not have a clear understanding of the design goals of the program they are working on, which can lead to incorrect or inefficient use of access levels. 


#include <iostream>

using namespace std;

class Prim{
    protected:
        string name;

    public:
        void setName(string x) {
            name = x;
        }
};

class Sec : protected Prim{
    public:
        void printName() {
            cout << "Name from Prim Cls: " << name << endl;
        }

        void caller(string x) {
            setName(x);
        }
};

int main() {

    Sec Object;
    Object.caller("Samantha");
    Object.printName();

    return 0;
}

The Sec class inherits from the Prim class with the protected keyword. This means that all public and protected members of the Prim class become protected members of the Sec class. Therefore, Sec can access the protected name member of Prim, but other classes cannot access it.

The printName() method of Sec class accesses the name member and displays it to the console. The caller() method of Sec class calls the setName() method of the Prim class to set the value of name.

C++ OO Public Inheritance

Public inheritance in C++ is a type of inheritance where the public members of the base class are accessible in the derived class. In other words, when a class is derived from a base class using public inheritance, the public members of the base class become public members of the derived class. 

The purpose of public inheritance is to enable the derived class to access the functionality of the base class while also allowing it to extend or specialize the behavior of the base class. For example, a class representing a specific type of vehicle can inherit from a more general class representing a vehicle, allowing the specific class to inherit the general properties of all vehicles while also adding additional specific properties and behavior unique to that specific type of vehicle.

Public inheritance is a powerful mechanism for code reuse and abstraction, allowing programmers to build complex and flexible software systems from simpler building blocks.


#include <iostream>

using namespace std;

class Prim{
    protected:
        string name;

    public:
        void setName(string x) {
            name = x;
        }
};

class Sec : public Prim{
    public:
        void printName() {
            cout << "Name from Prim Cls: " << name << endl;
        }
};

int main() {

    Sec Object;
    Object.setName("Samantha");
    Object.printName();

    return 0;
}

This is an example of inheritance with a base class called Prim and a derived class called Sec. The Sec class inherits publicly from the Prim class using the colon : notation.

The Prim class has a protected member variable called name and a public member function called setName() that takes a string argument x and sets the value of name to x.

The Sec class has a public member function called printName() that prints out the value of name from the Prim class using the cout statement.

In the main() function, an object of the Sec class called Object is created, and the setName() function is called on it to set the value of name to "Samantha". Then the printName() function is called on the Object to print out the value of name which was set by the setName() function. The output of the program will be: "Name from Prim Cls: Samantha"

Tkinter Introduction - Top Widget, Method, Button

First, let's make shure that our tkinter module is working ok with simple  for loop that will spawn 5 instances of blank Tk window .  ...