如何根据条件选择结构

时间:2018-02-13 15:01:46

标签: c++ oop struct polymorphism

我有两个不同的'结构''学生'& '雇员'。我想根据消息中提到的字符串选择它。

struct student {
   string name;
   float score;
}

struct employee {
   int id;
   string dep;
}

我收到消息; $ST,16,JOHN,A$EM,16,IT

从关键字STEM开始,我必须决定填充哪个结构。

我设法提取类似STEM的类型但是当我写的时候,

if (type == "ST")
    student x;
else if (type == "EM")
    employee x;
// long code goes on here to sort and populate `struct`

它说x未定义。我知道这是错的,但我无法解决这个问题。

如何根据条件选择struct

3 个答案:

答案 0 :(得分:1)

首先,看起来你的范围是错误的。因此x可能不可见。

不知道你的代码是如何看的,但你可以定义一个基类,一个指针在条件之前,并通过条件分配内存(我不会这样做)。或者,您需要在正确的范围内工作。

struct base {
    //whatever
};

struct student : public base  {
};
struct employee : public base {
};

base *ptr;
if (type == "ST")
    ptr = new student;
else if (type == "EM")
    ptr = new employee;

答案 1 :(得分:0)

if语句相当于

if (type == "ST") {
    student x;
} else if (type == "EM") {
    employee x;
}

// other code accessing x

您可以看到student xemployee x附近的范围。范围结束时,对象x也超出范围。

要正确填充结构,必须处理范围

中的结构
if (type == "ST") {
    student x;
    // populate student
} else if (type == "EM") {
    employee x;
    // populate employee
}

答案 2 :(得分:0)

如果你想要一些常见的事情。除了从字符串本身读取之外什么也没有。您可以创建对象,然后就地读取字符串。或者这个解决方案使用(种类)抽象工厂模式:

using namespace std;

// "Marker interface" common between the two structs.
// Virtual destructor to make this object polymorphic.
class ReadableFromString { public: virtual ~ReadableFromString() {} };

struct student: public ReadableFromString {
   string name;
   int score;
   char grade;
};

struct employee: public ReadableFromString {
  int id;
  string dept;
};

// Abstract factory function that creates a ReadableFromString
// from a string.
shared_ptr<ReadableFromString> readFromString(const string &source) {
    std::stringstream s(source);
    std::stringbuf buf(ios_base::out);
    string type;
    s.get(buf, ',');
    s.get(); // This is to skip the comma
    type = buf.str();
    if (type == "$ST") {
        shared_ptr<student> studentObj = make_shared<student>();
        s >> studentObj->score;
        s.get(); // This is to skip the comma
        buf = std::stringbuf(ios_base::out);
        s.get(buf, ',');
        studentObj->name = buf.str();
        s.get(); // This is to skip the comma
        studentObj->grade = s.get();
        s.get(); // This is to skip the comma
        return studentObj;
    }
    else if (type == "$EM") {
        shared_ptr<employee> employeeObj = make_shared<employee>();
        s >> employeeObj->id;
        s.get(); // This is to skip the comma
        buf = std::stringbuf(ios_base::out);
        s.get(buf, ',');
        employeeObj->dept = buf.str();
        s.get(); // This is to skip the comma
        return employeeObj;
    }
    return shared_ptr<ReadableFromString>(); // A null pointer
}

int main() {
    string sources[] = { "$ST,16,JOHN,A", "$EM,16,IT"};
    for(int i=0;i<2;i++) {
        shared_ptr<ReadableFromString> firstOne = readFromString(sources[i]);
        // Try to cast to student
        if (dynamic_pointer_cast<student>(firstOne)) {
            shared_ptr<student> studentObj = dynamic_pointer_cast<student>(firstOne);
            cout << "Student: " << "\n";
            cout << studentObj->name << "\n";
            cout << studentObj->score << "\n";
            cout << studentObj->grade << "\n";
        } else if (dynamic_pointer_cast<employee>(firstOne)) {
            // If not student, it could be an employee
            shared_ptr<employee> employeeObj = dynamic_pointer_cast<employee>(firstOne);
            cout << "Employee: " << "\n";
            cout << employeeObj->id << "\n";
            cout << employeeObj->dept << "\n";
        } else {
            cout << "Not student nor employee" << "\n";
        }
    }
    return 0;
}