성기덕
성기덕

Reputation: 43

How to check which objects in vector in C++

Well, Hospital is the class which has vector of patients. FemaleIn, FemaleOut, MaleIn, MaleOut are derived classes from patients(Base class). Those classes have toString function(method). What I am trying to do is, in display method in Hospital class, I just want to display only in case of Outpatient which is parent class of FemaleOut and Maleout or Inpatient which is parent class of FemaleIn and MaleIn. From what I am thinking to call only specific method from, for example, Outpatient, I will have to know which objects in which index of vector for automatically. Is there any idea to call only toString for specific class which is, for example, FemaleIn and MaleIn where parent class is Inpatient. Thank you for your any help or suggestion.

void Hospital::determinePatientType()
{
    int selection;
    cout << endl;
    cout << "What is the patient type?" << endl;
    cout << "1. Female Inpatient" << endl;
    cout << "2. Female Outpatient" << endl;
    cout << "3. Male Inpatient" << endl;
    cout << "4. Male Outpatient" << endl;
    cout << endl;
    cin >> selection;

    switch(selection)
    {
    case 1:
        patients.push_back(new FemaleIn());
        cout << patients.back() << endl;
        patients[totalPatients]->enterPatientData();
        totalPatients++;
        break;
    case 2:
        patients.push_back(new FemaleOut());
        cout << patients.back() << endl;
        patients[totalPatients]->enterPatientData();
        totalPatients++;
        break;
    case 3:
        patients.push_back(new MaleIn());
        cout << patients.back() << endl;
        patients[totalPatients]->enterPatientData();
        totalPatients++;
        break;
    case 4:
        patients.push_back(new MaleOut());
        cout << patients.back() << endl;
        patients[totalPatients]->enterPatientData();
        totalPatients++;
        break;
    default:
        return;
    }

}

void Hospital::display(string type)
{


        cout << "Patient Name     Spouse Name    Sex    Patient Type    Unit/Appt. Date    Diagnosis" << endl;
        cout << "===================================================================================" << endl;

        if(type=="All")
        {
            for(int i=0;i<patients.size();i++)
            {
                patients[i]->toString();
            }

        }
        else if(type=="Outpatient")
        {
            for(int i=0;i<patients.size();i++)
            {
                patients[i]->toString();
            }
        }
        else
        {
            for(int i=0;i<patients.size();i++)
            {
                patients[i]->toString();
            }
        }

}

Upvotes: 1

Views: 301

Answers (2)

user2807083
user2807083

Reputation: 2982

As quick and dirty way you can use dynamic_cast to certain class pointer to detect whether given instance is of that class:

    if (type == "Outpatient")
    {
        for(int i=0; i<patients.size(); ++i)
        {
            // try to cast parent class pointer to one of child class
            // if one is pointer to that child class p is not nullptr
            // otherwise p is nullptr
            Outpatient * p = dynamic_cast<Outpatient *>(patients[i]);

            if (p) {
                p->toString();
            }
        }
    }

For clean way you could use Visitor pattern

Visitor pattern implementation:

#include <iostream>
#include <vector>
#include <string>
#include <functional>
#include <utility>

class AbstractDirectionPatientsDispatcher;
class AbstractGenderPatientDispatcher;

class Patient
{
public:
    virtual void accept(AbstractDirectionPatientsDispatcher &dispatcher) = 0;
    virtual void accept(AbstractGenderPatientDispatcher &dispatcher) = 0;

    std::string name;
};

class InPatient;
class OutPatient;

class AbstractDirectionPatientsDispatcher {
public:
    virtual void dispatch(InPatient &patient) = 0;
    virtual void dispatch(OutPatient &patient) = 0;
};

class FemalePatient;
class MalePatient;

class AbstractGenderPatientDispatcher {
public:
    virtual void dispatch(FemalePatient &patient) = 0;
    virtual void dispatch(MalePatient &patient) = 0;
};

template <typename PatientClass, typename Dispatcher>
class CRTPDispatchApplier : virtual public Patient
{
public:
    void accept(Dispatcher &dispatcher) override {
        dispatcher.dispatch(static_cast<PatientClass &>(*this));
    }
};

class InPatient : public CRTPDispatchApplier<InPatient, AbstractDirectionPatientsDispatcher>
{
};

class OutPatient : public CRTPDispatchApplier<OutPatient, AbstractDirectionPatientsDispatcher>
{
};

class FemalePatient : public CRTPDispatchApplier<FemalePatient, AbstractGenderPatientDispatcher>
{
};

class MalePatient : public CRTPDispatchApplier<MalePatient, AbstractGenderPatientDispatcher>
{
};


class InFemale : public FemalePatient, public InPatient
{
};

class OutFemale : public FemalePatient, public OutPatient
{
};

class InMale : public MalePatient, public InPatient
{
};

class OutMale : public MalePatient, public OutPatient
{
};

class DummyDirectionDispatecher : public AbstractDirectionPatientsDispatcher
{
public:
    void dispatch(InPatient & ) override {
    }

    void dispatch(OutPatient & ) override {
    }
};

class DummyGenderDispatcher : public AbstractGenderPatientDispatcher
{
public:
    void dispatch(FemalePatient &) override {
    }

    void dispatch(MalePatient &) override {
    }
};

template <typename Direction>
class DispatchByDirection : public DummyDirectionDispatecher
{
public:
    DispatchByDirection(std::function<void(Direction &)> action) :
        m_action(std::move(action))
    {}

    void dispatch(Direction & p) override {
        m_action(p);
    }

private:
    std::function<void(Direction &)> m_action;
};

template <typename Gender>
class DispatchByGender : public DummyGenderDispatcher
{
public:
    DispatchByGender(std::function<void(Gender &)> action) :
        m_action(std::move(action))
    {}

    void dispatch(Gender & p) override {
        m_action(p);
    }

private:
    std::function<void(Gender &)> m_action;
};

int main() {
    InFemale f1;
    OutFemale f2;
    InMale m1;
    OutMale m2;
    f1.name = "Eve";
    f2.name = "Alice";
    m1.name = "Bob";
    m2.name = "Charlie";

    std::vector<Patient *> patients;
    patients.push_back(&f1);
    patients.push_back(&f2);
    patients.push_back(&m1);
    patients.push_back(&m2);

    DispatchByDirection<InPatient> print_in_patients{[](InPatient &patient){
        std::cout << "in: " << patient.name << std::endl;
    }};

    for (auto p : patients) {
        p->accept(print_in_patients);
    }
    std::cout << std::endl;

    DispatchByDirection<OutPatient> print_out_patients{[](OutPatient &patient) {
        std::cout << "out: " << patient.name << std::endl;
    }};

    for (auto p : patients) {
        p->accept(print_out_patients);
    }
    std::cout << std::endl;

    DispatchByGender<FemalePatient> print_female{[](FemalePatient &patient) {
        std::cout << "female: " << patient.name << std::endl;
    }};

    for (auto p : patients) {
        p->accept(print_female);
    }
    std::cout << std::endl;

    DispatchByGender<MalePatient> print_male{[](MalePatient &patient) {
        std::cout << "male: " << patient.name << std::endl;
    }};

    for (auto p : patients) {
        p->accept(print_male);
    }
    std::cout << std::endl;
}

Upvotes: 0

Nicol&#225;s Abram
Nicol&#225;s Abram

Reputation: 333

I think this question might be similar to How do I check if an object's type is a particular subclass in C++? .

I would propose something like:

Class Patient{
    virtual bool display(string filter);
};
Class OutPatient : Patient {
    bool display(string filter) override;
};
bool OutPatient::display(string filter) {
    if (filter != "OutPatient")
        return false;
    //Do stuff
    return true;
}
Class InPatient : Patient {
    bool display(string filter) override;
};
// You could just make this the default definition on display on Patient
bool InPatient::display(string filter) {
    return false;
}

And then:

void Hospital::display(string type)
{
    for(auto& patient: patients)
        patient->display(type);
}

Upvotes: 3

Related Questions