C ++ - 正确访问联合中的嵌套结构

时间:2017-11-12 20:46:26

标签: c++ struct unions

我正在为学校开展一个项目,需要让这个代码结构正常运行。 问题:我需要正确访问联合成员(h和s),而不需要随机获取大量内存数据 - 并且实际上取回我存储的数字。我理解联合如何工作所以我很困惑为什么我的代码给我随机数据而不是我存储在那里的数字。 注意:我确实在寻找这个问题的其他答案(因为这听起来像一个非常常见的语法问题),但其他解决方案并不适合我的情况。

#include <iostream>
#include <string>
#include <iomanip>
using namespace std;

struct worker {
    enum kind {NOTSALARIED, ISSALRIED};
    bool isSalaried;

    union {
        struct hourly{
            double numberHours;
            double hourlyRate;
        } h; // end of 'hourly' struct
        struct salaried{
            double salaryAmount;
            double bonusAmount;
        } s; // end of 'salaried' struct
    } info; // end of 'info' union
};

/// PROTOTYPE section
worker* getHourly();
worker* getSalaried();
void printWorker(worker);

int main() {
    worker *theWorker; // avoids making another 'worker' object for no reason

    // format code for 'double' values
    cout << fixed << showpoint << setprecision(2);

    // used string so avoid user entering name with the correct first character
    string choice;
    cout << "(H)ourly or (S)alary? ";
    getline(cin, choice);

    /// LOGIC SECTION: Checks what the user entered
    if(choice == "H" || choice == "h") {
        // get the salary
        theWorker = getHourly();
        // pass in the dereferenced pointer to print out the info
        printWorker(*theWorker);
    }
    if(choice == "S" || choice == "s") {
        // get the salary
        theWorker = getSalaried();
        // pass in the dereferenced pointer to print out the info
        printWorker(*theWorker);
    }

    return 0;
}

 // method that gets the information -- creates a new worker object --     returns a pointer to the object
worker* getHourly() {
    worker newWorker;

    // set the isSalaried equal to false
    newWorker.isSalaried = worker::NOTSALARIED; // equals 0 -- FALSE

    cout << "Enter the number of hours worked: ";
    // take in the hours worked
    cin >> newWorker.info.h.numberHours;

    cout << "Enter the hourly pay rate: ";
    // take in the hourly rate
    cin >> newWorker.info.h.hourlyRate;

    return &newWorker;
}

worker* getSalaried() {
    worker newWorker;

    // set the kind equal to SALARIED
    newWorker.isSalaried = worker::ISSALARIED; // equals 1 -- TRUE

    cout << "Enter the salary amount: ";
    // take in the salary
    cin >> newWorker.info.s.salaryAmount;

    cout << "Enter the bonus amount: ";
    // take in the bonus
    cin >> newWorker.info.s.bonusAmount;

    return &newWorker;
}

void printWorker(worker theWorker) {
    double grossPay;

    // take care of the SALARIED first
    if (theWorker.isSalaried) {
        // add the salary to the bonus amount
        grossPay = (theWorker.info.s.salaryAmount + theWorker.info.s.bonusAmount);

        // print out the info
        cout << "Salaried Worker" << endl;
        // print out the salary
        cout << "Salary: $" << theWorker.info.s.salaryAmount << endl;
        // print out the bonus
        cout << "Bonus: $" << theWorker.info.s.bonusAmount << endl;
    }
    // now, take care of the HOURLY
    if ( !(theWorker.isSalaried) ) {
        // get the product of the number of hours worked and the hourly rate
        grossPay = (theWorker.info.h.numberHours * theWorker.info.h.hourlyRate);

        // print out the info
        cout << "Hourly Worker" << endl;
        // print out the number of hours worked
        cout << "\tHours: " << theWorker.info.h.numberHours << endl;
        // print out the rate
        cout << "\tRate: $" << theWorker.info.h.hourlyRate << endl;
    }

    // print out the last portion here, since this code will be executed for both
    cout << "\t--------" << endl;
    cout << "\tGross Pay: $" << grossPay << endl;
}

3 个答案:

答案 0 :(得分:1)

你在...中得到了大块......

worker* getSalaried() {
    worker newWorker;
    ...
    return &newWorker;
}

您返回本地变量的地址。因此,newWorker的生命周期在getSalaried完成后结束,并且在生命终结后访问对象是未定义的行为(例如,提供&#34; chunk&#34;)。为了解决这个问题,你可以返回一个worker - struct本身(不是指向它的指针),或者你可以将worker的实例传递给函数,这样就可以直接写入它。 / p>

答案 1 :(得分:0)

为了充实这里的答案中的评论,我建议你实际阅读你的编译器所说的内容。例如:

bla.cpp:57:12: warning: address of local variable ‘newWorker’ returned [-Wreturn-local-addr]
 worker newWorker;

如果你没有看到这个,你应该打开警告标志 - 虽然我猜你只是忽略了它。另一个无关的错误:

bla.cpp:77:28: error: ‘ISSALARIED’ is not a member of ‘worker’
 newWorker.isSalaried = worker::ISSALARIED; // equals 1 -- TRUE

这是一个错字。你需要做的是按值传递东西,所以复制结构,或者开始处理动态内存 - 不确定你现在想要这个。按值返回(复制struct)或示例:

worker getSalaried() {
    worker newWorker;

    // set the kind equal to SALARIED
    newWorker.isSalaried = worker::ISSALARIED; // equals 1 -- TRUE

    cout << "Enter the salary amount: ";
    // take in the salary
    cin >> newWorker.info.s.salaryAmount;

    cout << "Enter the bonus amount: ";
    // take in the bonus
    cin >> newWorker.info.s.bonusAmount;

    return newWorker;
}

我不确定你是否正在开始面向对象编程,但是两个get函数看起来应该是你的worker的一个构造函数,并且打印一个公共方法。这样你就可以避免处理这个问题了。

答案 2 :(得分:0)

我在代码块上尝试了上面的代码,但它确实有效,但我确信这段代码每次运行都不安全。 你的问题的原因是:你的2个功能

worker* getHourly()
{
    worker newWorker;
        ...
        return &newWorker;
}

worker* getSalaried() {
    worker newWorker;
     ...
     return &newWorker;
}

在这两个函数中,您从worker创建一个局部变量,然后将其地址返回给main处的调用者。 由于局部变量从内存中删除,在函数终止后,所以,主要指针“theWorker”,在不属于你的内存中保存一个地址,这可能会导致你的问题。 你必须做出两个解决方案之一: 第一个,保持函数不变,但在函数中,定义一个指针而不是变量,并将其分配为动态分配,如下所示:

worker* getHourly()
{
    worker* newWorker;
     newWorker = new (worker)        
     ...
        return newWorker;
}

worker* getSalaried() {
    worker* newWorker;
     newWorker = new (worker);
     ...
     return &newWorker;
}

第二个:让2函数返回变量而不是地址如下:

worker getHourly()
{
    worker newWorker;
     ...
        return newWorker;
}

worker getSalaried() {
    worker newWorker;
     ...
     return &newWorker;
}