我最初在CodeReview上问了这个问题。由于那里的接待不佳(完全是我的错),我认为这是问的正确地方。我要在此处复制我在那儿问过的完全相同的问题(进行一些小的修改)。

我的目标是尽可能使用STL功能以C ++编写CPU调度模拟器。到目前为止,我只编写了FCFS的代码,还没有提供任何输入方法。

对我来说最突出的是流程类的定义。我设计程序的方式,封装很差。从我目前的情况来看,我只有两种解决方案:


将所有数据成员设为私有。为PID,到达时间和突发时间提供访问器,并为其余部分提供变量器。但是,我担心这会使我的代码肿,而且使用mutator只会破坏封装。
使FCFS()displayResult()和我添加的friend类的process的任何其他算法。这使我可以在一定程度上控制封装,因此我很喜欢这种封装。


我试图做的另一件事是使PID,到达时间和突发时间变量const公开。这允许算法读取它们的值,但不能修改它们。但是,由于const成员不是默认可分配的,因此无法编译代码。

我想就如何解决上述问题以及如何更有效地使用STL使代码更具表现力提出建议。

#include <iostream>
#include <vector>
#include <algorithm>
#include <limits>

constexpr int notYetComputed = std::numeric_limits<unsigned int>::max();

struct process
{
    unsigned int m_procId;
    unsigned int m_arrivalTime;
    unsigned int m_burstTime;

    unsigned int m_responseTime;
    unsigned int m_completionTime;
    unsigned int m_turnaroundTime;
    unsigned int m_waitingTime;

    process(unsigned int pid, unsigned int at, unsigned int bt)
        : m_procId {pid}, m_arrivalTime {at}, m_burstTime {bt}
    {
        m_waitingTime = m_turnaroundTime = m_completionTime = m_responseTime = notYetComputed;
    }
};

void displayResult(const std::vector<process>& procs)
{
    for(auto& x : procs)
        std::cout << "PID: " << x.m_procId << ", "
            << "Waiting Time: " << x.m_waitingTime << ", "
            << "Turnaround Time: " << x.m_turnaroundTime << ", "
            << "Response Time: " << x.m_responseTime << ", "
            << "Completion Time: " << x.m_completionTime << "\n";
}
void FCFS(std::vector<process>& procList)
{
    //Sort based on arrival order. Use PID in case of same arrival time.
    auto arrivalOrder = [] (const process& p1, const process& p2) {
        if(p1.m_arrivalTime < p2.m_arrivalTime) return true;
        if(p1.m_arrivalTime == p2.m_arrivalTime) return (p1.m_procId < p2.m_procId);
        return false;
    };
    std::sort(procList.begin(), procList.end(), arrivalOrder);

    unsigned int clock {0};
    auto computeResult = [&clock] (process& pr) {
        pr.m_responseTime = clock - pr.m_arrivalTime;
        pr.m_waitingTime = (pr.m_turnaroundTime =
            (pr.m_completionTime = (clock += pr.m_burstTime)) - pr.m_arrivalTime)
            - pr.m_burstTime;
    };

    std::for_each(procList.begin(), procList.end(), computeResult);

}

int main()
{
    std::vector<process> procs {{0,0,5}, {1,1,3}, {2,2,8}, {3,3,6}};

    FCFS(procs);

    //Sort based on PID before showing result
    std::sort(procs.begin(), procs.end(),
        [](const process& p1, const process& p2) {
            return p1.m_procId < p2.m_procId;
    });

    displayResult(procs);
}


更新:
我打算将来增加更多的调度算法。所以我更喜欢Jarod42的思路。我真的不能将特定于算法的代码作为process类的一部分。

最佳答案

您的流程类同时包含输入和输出成员。

我将它们分开(我使用的名称可能应该改进)以明确说明流程(并且我们可以摆脱notYetComputed,这似乎对我来说是一个hack):

struct process_input
{
    unsigned int m_procId;
    unsigned int m_arrivalTime;
    unsigned int m_burstTime;
};

struct process_ouput
{
    unsigned int m_responseTime;
    unsigned int m_completionTime;
    unsigned int m_turnaroundTime;
    unsigned int m_waitingTime;
};

struct process
{
    process_input m_input;
    process_output m_output;
};


FCFS将显示流,因此std::vector<process> FCFS(std::vector<process_input> inputs)

经过一些样式更改,它变为:

std::vector<process> FCFS(std::vector<process_input> inputs)
{
    // Sort based on arrival order. Use PID in case of same arrival time.
    auto proj = [](const process_input& p){ return std::tie(p.m_arrivalTime, p.m_procId); };
    auto compare = [&] (const process& lhs, const process& rhs) {
        return proj(lhs) < proj(rhs);
    };
    std::sort(inputs.begin(), inputs.end(), compare);

    std::vector<process> res;
    res.reserve(inputs.size());
    unsigned int clock {0};

    auto computeOutput = [] (const process_input& pr, unsigned int& clock) {
        process_ouput res;

        res.m_responseTime = clock - pr.m_arrivalTime;
        clock += pr.m_burstTime;
        res.m_completionTime = clock;
        res.m_turnaroundTime = res.m_completionTime - pr.m_arrivalTime;
        res.m_waitingTime = res.m_turnaroundTime - pr.m_burstTime;
        return res;
    };

    for (auto& input : inputs) {
        res.push_back({input, computeOutput(input, clock)});
    }
    return res;
}


main更改为:

int main()
{
    std::vector<process> inputs {{0,0,5}, {1,1,3}, {2,2,8}, {3,3,6}};

    auto procs = FCFS(inputs);

    //Sort based on PID before showing result
    std::sort(procs.begin(), procs.end(),
        [](const process& p1, const process& p2) {
            return p1.m_input.m_procId < p2.m_input.m_procId;
    });

    displayResult(procs);
}


现在我们要保留哪些保证?


process_input是没有内部约束的简单数据。
process_output是简单数据,似乎也没有内部约束。
process在输入和输出之间应该具有一致性:因此,不能对其成员进行非const访问。


// const member might be enough in that case,
// but I prefer to avoid const members
// which make class harder to use (not movable, not assignable, ....)
// so only const getters
struct process
{
public:
    const process_input& input() const { return m_input;
    const process_output& output() const { return m_outnput; }

private:
    process_input m_input;
    process_output m_output;
};


作为getter的替代或补充,您可以在此处添加Display方法。

关于c++ - 如何重新设计/修复此程序以允许封装?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57240661/

10-12 16:02