Search code examples
c++classoopmultiple-inheritance

Inheritance in C++ for a class project


In the image what is written in black are variables specific for each class and what is blue is inherited from the client class. This is pretty much what I want to doI have class project in C++ about an SMMA where I have these classes: Client, Campaign, Analytics, Invoice, Post. Note that I must use inheritance.

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;

class IOinterface{
public:
    virtual istream& input(istream&) = 0;
    virtual ostream& output(ostream&) const = 0;
};

class Client {
    protected:
        char* client_name;
        const int clientID;
        static int numberOfClients;
        string company;
        long marketing_budget;
        bool contract;
    public:
        void setClientName(const char* newClientName) {
            if(this->client_name != nullptr) {
                delete[] this->client_name;
                this->client_name = nullptr;
            }
            this->client_name = new char [strlen(newClientName) + 1];
            strcpy(this->client_name, newClientName);
        }
        const char* getClientName() const {return this-> client_name;}

        void setCompany(string newCompany) {this->company = newCompany;}
        string getCompany() {return this->company;}

        
        void setMarketingBudget(long newMarketingBudget) {this->marketing_budget = newMarketingBudget;}
        long getMarketingBudget() {return this->marketing_budget;}
    

        void setContract(bool newContract) {this->contract = newContract;}
        bool getContract() {return this->contract;}

        Client();
        Client(const char* client_name, const string company, const long marketing_budget, const bool contract);
        Client(const Client& obj);

        Client& operator=(const Client& obj);

        ~Client();

        friend istream& operator>>(istream& in, Client& obj);
        friend ostream& operator<<(ostream& out, const Client& obj);

};

int Client::numberOfClients = 0;

Client::Client():clientID(++numberOfClients){
    this->client_name = new char[strlen("NULL") + 1];
    strcpy(this->client_name, "NULL");
    this->company = "NULL";
    this->marketing_budget = 0;
    this->contract = 0;
}

Client::Client(const char* client_name, const string company, const long marketing_budget, const bool contract):clientID(++numberOfClients) {
    this->client_name = new char[strlen(client_name) + 1];
    strcpy(this->client_name, client_name);
    this->company = company;
    this->marketing_budget = marketing_budget;
    this->contract = contract;
}

Client::Client(const Client& obj):clientID(++numberOfClients) {
    this->client_name = new char[strlen(obj.client_name) + 1];
    strcpy(this->client_name, obj.client_name);
    this->company = obj.company;
    this->marketing_budget = obj.marketing_budget;
    this->contract = obj.contract;
}

Client& Client::operator=(const Client& obj) {
    if(this != &obj) {
        if(this->client_name != nullptr) {
            delete[] this->client_name;
            this->client_name = nullptr;
        }
        this->client_name = new char[strlen(obj.client_name) + 1];
        strcpy(this->client_name, obj.client_name);
        this->company = obj.company;
        this->marketing_budget = obj.marketing_budget;
        this->contract = obj.contract;
    }
    return *this;
}

Client::~Client() {
    if (this->client_name != nullptr) {
        delete[] this->client_name;
        this->client_name = nullptr;
    }
}

istream& operator>>(istream& in, Client& obj) {
    cout << "Client name: ";
    char name[150];
    in.getline(name, 150);
    if (obj.client_name != nullptr) {
        delete[] obj.client_name;
        obj.client_name = nullptr;
    }
    obj.client_name = new char[strlen(name) + 1];
    strcpy(obj.client_name, name);
    cout << "Company: ";
    getline(in, obj.company);
    cout << "Marketing budget: ";
    in >> obj.marketing_budget;
    cout << "Contract: ";
    in >> obj.contract;

    return in;
}

ostream& operator<<(ostream& out, const Client& obj) {
    out << "---------------------------------------------------" << endl;
    out << "ClientID: " << obj.clientID << "\n";
    out << "Client name: "<< obj.client_name << "\n";
    out << "Number of clients: " << obj.numberOfClients << "\n";
    out << "Company: " << obj.company << "\n";
    out << "Marketing budget: " << obj.marketing_budget << "\n";
    out << "Contract: " << obj.contract << "\n";
    out << "---------------------------------------------------" << endl;

    return out;
};

class Campaign : public IOinterface, virtual public Client {
    private:
        char* campaign_name;
        vector<string> objectives;
        string socialMediaPlatform;
    public:
        void setCampaignName(const char* newCampaignName) {
            if(this->campaign_name != nullptr) {
                delete[] this->campaign_name;
                this->campaign_name = nullptr;
            }
            this->campaign_name = new char[strlen(newCampaignName) + 1];
            strcpy(this->campaign_name, newCampaignName);
        }
        const char* getCampaignName() {return this->campaign_name;}

        void setObjectives(const vector<string>& newObjectives) {this->objectives = objectives;}
        const vector<string>& getObjectives() {return this-> objectives;}

        void setSocialMediaPlatform(string newSocialMediaPlatform) {this->socialMediaPlatform = newSocialMediaPlatform;}
        string getSocialMediaPlatform() {return this->socialMediaPlatform;}

        Campaign();
        Campaign(const char* campaign_name, const vector<string> objectives, const string socialMediaPlatform);
        Campaign(const Campaign& obj);

        Campaign& operator=(const Campaign& obj);

        ~Campaign();

        friend istream& operator>>(istream& in, Campaign& obj);
        friend ostream& operator<<(ostream& out, const Campaign& obj);

};

Campaign::Campaign() {
    this->campaign_name = new char[strlen("NULL") + 1];
    strcpy(this->campaign_name, "NULL");
    this->objectives = {};
    this->socialMediaPlatform = "NULL";
};

Campaign::Campaign(const char* campaign_name, const vector<string> objectives, const string socialMediaPlatform) {
    this->campaign_name = new char[strlen(campaign_name) + 1];
    strcpy(this->campaign_name, campaign_name);
    this->objectives = objectives;
    this->socialMediaPlatform = socialMediaPlatform;
}

Campaign::Campaign(const Campaign& obj) {
    this->campaign_name = new char[strlen(obj.campaign_name) + 1];
    strcpy(this->campaign_name, obj.campaign_name);
    this->objectives = obj.objectives;
    this->socialMediaPlatform = obj.socialMediaPlatform;
}

Campaign& Campaign::operator=(const Campaign& obj) {
    if (this != &obj) {
        if(this->campaign_name != nullptr) {
            delete[] this-> campaign_name;
            this->campaign_name = nullptr;
        }
        this->campaign_name = new char[strlen(obj.campaign_name) + 1];
        strcpy(this->campaign_name, obj.campaign_name);
        this->objectives = obj.objectives;
        this->socialMediaPlatform = obj.socialMediaPlatform;
    }
    return *this;
}

Campaign::~Campaign() {
    if(this->campaign_name != nullptr) {
        delete[] this->campaign_name;
        this->campaign_name = nullptr;
    }
}

istream& operator>>(istream& in, Campaign &obj) {
    cout << "Campaign name: ";
    char name[100];
    in.getline(name, 100);
    if(obj.campaign_name != nullptr) {
        delete[] obj.campaign_name;
        obj.campaign_name = nullptr;
    }
    obj.campaign_name = new char[strlen(name) + 1];
    strcpy(obj.campaign_name, name);
    cout << "Objectives: ";
    string temp;
    while(getline(in, temp)) {
        if (temp.empty()) { 
            break;
        }
        obj.objectives.push_back(temp);
        cout << "Enter another objective (or press Enter to finish): ";
    }
    cout << "Social media platform: ";
    in >> obj.socialMediaPlatform;

    return in;
}

ostream& operator<<(ostream& out, const Campaign& obj) {
    out << "---------------------------------------------------" << endl;
    out << "Campaign name: " << obj.campaign_name << "\n";
    out << "Objectives: ";
    for (int i = 0; i < obj.objectives.size(); i++)
        if (i == 0) {
            out << "-" << obj.objectives[i] << endl;
        } else {
            out << "            -" << obj.objectives[i] << endl;
        }
    out << "Social media platform: " << obj.socialMediaPlatform << "\n";
    out << "---------------------------------------------------" << endl;

    return out;
}



int main() {
    Campaign a("pix", {"bani", "likes"}, "Instagram"), b;
    cin>>b;
    cout <<b;

}

I want when I type

int main() {
 Client A;
 Campaign B;
 cin >> A >> B;
 cout << B;
}

to be prompted to enter details about a Client object, then details about a Campaign object, then when it executes "cout << B" I want to see on the screen all the information specific to the Campaign object and also some things inherited from the Client object. Instead, for those things inherited from the Client object, it shows NULL or 0, like in the default constructor of the class.


Solution

  • Here's how you can achieve what you want with your existing code

    int main()
    {
        Client A;
        cin >> A;
        Campaign B;
        cin >> B;
        B.setClientName(A.getClientName());
        B.setCompany(A.getCompany());
        // etc etc
    }
    

    Essentially you have to copy all the client information from A to B.

    This is not a good design. Inheritance should be used to model relationships when one class is a specialization of another class, e.g. a Circle is a Shape. These kind of relationships are sometimes called is-a relationships. When one class has another class as an attribute those are called has-a relationships, e.g. a Campaign has a Client. These kind of relationships are best modelled using member variables not inheritance. So your code would be much better rewritten to use membership instead of inheritance something like this

    class Client
    {
        ...
    };
    
    class Campaign // no inheritance from Client
    {
    public:
        Client getCLient() const { return client; }
        void setClient(const Client& c) { client = c; }
        ...
    private:
        ...
        Client client; // client member
    };
    
    int main()
    {
        Client A;
        cin >> A;
        Campaign B;
        cin >> B;
        B.setClient(A);
    }