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

C++ - Properly accessing nested struct in union

我正在为学校做一个项目,需要建立这种代码结构并使其正常工作。 问题: 我需要正确访问联合成员(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;
}

自从...

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

你return一个局部变量的地址。因此 newWorker 的生命周期在 getSalaried 结束后结束,并且在其生命周期结束后访问对象是未定义的行为(例如提供 "chunk")。为了克服这个问题,你可以 return 一个 worker-struct 本身(不是指向它的指针),或者你可以将 worker 的实例传递给函数,这样它就可以直接写进去。

我在代码块上尝试了上面的代码,它可以工作,但我确信这段代码每次都不安全 运行。 你的问题的原因是:你的 2 function

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

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

在这 2 个函数中,您从 worker 创建一个局部变量,然后您 return 将其地址编辑到 main 的调用者。 由于局部变量已从内存中删除,因此在函数终止后,main 中的指针 "theWorker" 在内存中保存了一个不再属于您的地址,这可能会导致您的问题。 你必须做出两种解决方案之一: 第一个,保持函数原样,但在函数中,定义一个指针而不是变量,并将其分配为动态分配如下:

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

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

第二种:让2函数return一个变量代替地址如下:

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

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