【问题标题】:Need help on where i should call a virtual function需要关于我应该在哪里调用虚函数的帮助
【发布时间】:2020-03-21 01:09:25
【问题描述】:

抱歉,代码太长了,让我简单解释一下。我做了一个主类 - 工人和两个派生类 - 小时工,受薪工人。我做了一个计算工资的虚函数,不用解释了,这不是我的问题。

我读了一个输入,这里是一个例子:

3 //我读取的第一个数字决定了我将拥有多少工人

戴夫·萨尔

史蒂夫·侯

chris sal //这 3 行显示工人的姓名,以及他们是按工资还是按小时支付的

10 20 10 //这 3 名工人的工作时间,按此顺序。


这就是我想要做的:根据每个工人获得的付款类型(hou 或 sal),我计算他的薪水,调用虚函数 compute_pay。 示例输出:

戴夫 400

史蒂夫 200

克里斯400。 这是我的代码:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;

class Worker {
public:
    void print();
protected:
    string name;
    string type;
};

class HourlyWorker : public  Worker {
public:
    HourlyWorker(string n) {
        name = n;
    }
    virtual double compute_pay(int hours) {
        double payment = 10;
        if (hours <= 40) {
            return hours * payment;
        }
        else {
            return (40 * payment) + ((hours - 40) * payment * 1.5);
        }
    }
    void print(int a) {
        cout << name << "  " << a << "\n";
    }
private:
    string name;
    string type;
}

class SalariedWorker : public Worker{
public:
    SalariedWorker(string n) {
        name = n;
    }
    virtual double compute_pay(int hours) {
        hours = 40;
        int payment = 10;
        return payment * hours;
    }
    void print(int a) {
        cout << name << "  " << a << "\n";
    }
private:
    string name;
    string type;
};

void print(vector<SalariedWorker*> sal, int a)
{
    for (int i = 0; i < sal.size(); i++)
        sal[i]->print(a);
}
void print(vector<HourlyWorker*> sal, int a)
{
    for (int i = 0; i < sal.size(); i++)
        sal[i]->print(a);
}

int main()
{
    vector<SalariedWorker*> sal;
    vector<HourlyWorker*> hour;
    int first; //first digit
    int hours; //hours of each worker
    string name; //name or worker
    string type; //sal or hou
    cout << "go" << "\n";
    cin >> first;
    for (int i = 0; i < first+1; i++) {
        if (i < first) {
            cin >> name >> type;
            if (type == "sal") {
                SalariedWorker* sall = new SalariedWorker(name);
                sal.push_back(sall); //If a worker is "sal" i write into the HourlyWorker vector
            }
            else if (type == "hou") {
                HourlyWorker* hourr = new HourlyWorker(name);
                hour.push_back(hourr);
            } //If a worker is "hou" i write into the HourlyWorker vector
            else {
                cout << "Wrong input" << "\n";
                return 1;
            }
        }
        else { //This triggers when we reach the last line. It triggers only once
            for (int z = 0; z < first; z++) {
                cin >> hours; //reading the last line
            }
        }
    }
}

再次抱歉,代码太长了,您不必遍历所有代码,只需了解主类,更重要的是 - 循环。 这是我的问题:假设它需要的 int 变量是我在最后一行读取的 int hours 变量,我应该在哪里调用我的 compute_pay 函数以便它遍历所有行? 另外,之后我应该在哪里调用我的打印函数以便我可以看到我的输出? 我知道这是一个愚蠢或复杂的问题,但老实说,我尽了最大努力,但我无法弄清楚:/。

【问题讨论】:

  • 你能澄清你的问题吗?这很难理解。 “我应该在哪里调用我的 compute_pay 函数,以便它通过所有行” - 什么行? compute_pay“通过”一行是什么意思?正如所写,compute_pay 没有“经历”任何事情。
  • 抱歉造成误会。行我的意思是输入行。这是它应该如何工作的示例: 1 - 它读取一个人的名字。 2 - 它读取sal/hou(支付方式),并根据它将人置于两个向量之一——sal、小时。 3 - 在读取所有名称后,它会再读取一行 - 每个工人的工作时间。第一个数字是第一个工人,第二个是第二个,等等。这样做之后,根据付款的类型 - sal/hou 它调用函数 compute_pay 并以此方式计算付款。我应该在阅读最后一行时还是之后调用它?

标签: c++ inheritance vector virtual-functions


【解决方案1】:

在您的示例中,您有 Worker 的不同派生以及它们自己的 compute_pay 实现。拥有一个虚拟的compute_pay 的作用是让您可以通用地使用基类,而无需为每种类型设置单独的列表。

要普遍使用虚方法,您需要一个抽象基类。这意味着基类需要一个虚方法声明(以及一个虚析构函数):

class Worker {
public:
    virtual double compute_pay(int hours) = 0;
    virtual ~Worker() = default;
    /* all the other members go here */
};

虚析构函数是其中的一个重要部分——这意味着无论您使用什么类型的指针,都会调用正确的析构函数。 = 0 表示它是一个 纯虚拟 方法,如果您尝试声明基类 Worker 而不是派生类,则该方法未实现并且会中断。

派生类必须使用该类独有的逻辑覆盖该基础虚拟方法:

class WorkerA {
public:
    double compute_pay(int hours) override { /* whatever */ return 42.0; }
};
class WorkerB {
public:
    double compute_pay(int hours) override { /* whatever */ return 25.0; }
};

请注意,派生类不使用virtual,而是添加override 以表明它们应该覆盖虚拟基方法。

然后,您可以拥有 一个 工人向量:

std::vector<std::unique_ptr<Worker>> workers;

if (use_worker_a) {
    workers.emplace_back(new WorkerA());
} else {
    workers.emplace_back(new WorkerB());
}

注意:尽可能使用智能指针,例如unique_ptr,而不是原始指针,这样您就不必担心显式删除它们。

然后可以从该向量中使用基本虚拟方法,而无需关心哪个指针是哪个派生类型:

double sum = 0;
for (auto& worker : workers) {
    sum += worker->compute_pay(40);
}

关于计算小时数、从文件中读取等的所有内容,我都交给你了。但这就是您如何有效地使用虚拟方法进行动态调度的方式。

【讨论】:

    猜你喜欢
    • 2020-08-13
    • 2019-10-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 2014-03-11
    相关资源
    最近更新 更多