如何在C ++中检查向量中的哪些对象

时间:2018-03-19 14:31:26

标签: c++ inheritance vector base

嗯,Hospital是具有病人载体的类。 FemaleInFemaleOutMaleInMaleOut是患者的派生类(基类)。这些类具有toString函数(方法)。我想要做的是,在display类的Hospital方法中,我只想显示Outpatient的父类FemaleOut和{{} 1}}或Maleout,它是InpatientFemaleIn的父类。从我所想的只调用特定方法,例如MaleIn,我将不得不自动知道哪个对象在哪个矢量索引中。是否有任何想法仅针对特定类调用Outpatient,例如toStringFemaleIn,其中父类为MaleIn。感谢您的任何帮助或建议。

Inpatient

2 个答案:

答案 0 :(得分:3)

我认为这个问题可能类似于How do I check if an object's type is a particular subclass in C++?

我会建议像:

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;
}

然后:

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

答案 1 :(得分:0)

以快速和脏的方式,您可以使用dynamic_cast某个类指针来检测给定的实例是否属于该类:

    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();
            }
        }
    }

对于干净的方式,您可以使用Visitor pattern

访客模式实施:

#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;
}