设计计算机类的练习中出现的错误

发布于 2022-09-12 02:43:41 字数 5309 浏览 42 评论 0

我正在尝试设计一个计算机类,我想使用一个名为Work的函数来检查每个硬件的状态,但是在Dell / IBM类中使用时会失败(仅在PC类中使用时没有问题)。 我debug一小时没能找出错误原因。

源代码可以完成编译。

Work()位于第117行,该行具有FIXME标签

类之间的关系图在最后

这是源代码

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

class HardWare
{
private:
    string brand = "";

public:
    HardWare(string bra = "") : brand(bra) {}
    virtual ~HardWare() {}
    virtual void Set(HardWare *obj);

    
    virtual void work() {}
    string getBrand() { return brand; }
};

void HardWare::Set(HardWare *obj)
{
    brand = obj->brand;
}

class CPU : public HardWare
{
private:
    double frequency = 0.0;

public:
    CPU(string b = "", double f = 0.0) : HardWare(b), frequency(f) {}
    virtual ~CPU() {}
    virtual void Set(CPU *obj);

    void work();
    double getFrequency() { return frequency; }
};

void CPU::Set(CPU *obj)
{
    frequency = obj->frequency;
    HardWare::Set(obj);
}

void CPU::work()
{
    cout << getBrand() << " CPU Work with " << frequency << "GHz\n";
}

class MainBoard : public HardWare
{
private:
    string type = "";

public:
    MainBoard(string b = "", string t = "") : HardWare(b), type(t) {}
    virtual ~MainBoard() {}
    virtual void Set(MainBoard *obj);

    void work();
    string getType() { return type; }
};

void MainBoard::Set(MainBoard *obj)
{
    type = obj->type;
    HardWare::Set(obj);
}

void MainBoard::work()
{
    cout << getBrand() << " MainBoard Work with " << type << "\n";
}

class HardDisk : public HardWare
{
private:
    int store = 0;

public:
    HardDisk(string b = "", int s = 0) : HardWare(b), store(s) {}
    virtual ~HardDisk() {}
    virtual void Set(HardDisk *obj);

    void work();
    int getStore() { return store; }
};

void HardDisk::Set(HardDisk *obj)
{
    store = obj->store;
    HardWare::Set(obj);
}

void HardDisk::work()
{
    cout << getBrand() << " HardDisk Work with " << store << "G\n";
}


class PC
{
private:
    vector<HardWare *> computer;

public:
    void AddToPC(HardWare *obj);
    void Work();
};

void PC::AddToPC(HardWare *obj)
{
    computer.push_back(obj);
}

//FIXME117
void PC::Work()
{
    for (int i = 0; i <computer.size(); i++)
        computer[i]->work();

    cout << "PC Work\n";
    
}

class Builder 
{
public:
    virtual void ProduceCPU() = 0;
    virtual void ProduceHardDisk() = 0;
    virtual void ProduceMainBoard() = 0;
    virtual void ProducePC() = 0;

    virtual PC *GetPC() = 0;
};

class DellBuilder : public Builder
{
public:
    virtual void ProduceCPU(); 
    virtual void ProduceHardDisk();
    virtual void ProduceMainBoard();

    virtual void ProducePC(); 

    PC *GetPC(); 

private:
    PC *m_PC; 
};

void DellBuilder:: ProduceCPU(){
    string brand;
    double frequency;
    cin>>brand>> frequency;
    cin.get();

    HardWare* wcpu = new CPU(brand, frequency);
    m_PC->AddToPC(wcpu);

    delete wcpu;
}

void DellBuilder:: ProduceHardDisk(){
    string brand;
    unsigned int store;
    cin>>brand >> store;
    cin.get();

    HardWare *wdisk = new HardDisk(brand, store);
    m_PC->AddToPC(wdisk);

    delete wdisk;
}

void DellBuilder:: ProduceMainBoard(){
    string brand, type;
    cin >> brand >> type;
    cin.get();

    HardWare *wboard = new MainBoard(brand, type);
    m_PC->AddToPC(wboard);

    delete wboard;
}

void DellBuilder:: ProducePC(){
    m_PC = new PC();
}

PC * DellBuilder:: GetPC(){
    return m_PC;
}

class IBMBuilder : public Builder
{
public:
    virtual void ProduceCPU(); 
    virtual void ProduceHardDisk();
    virtual void ProduceMainBoard();

    virtual void ProducePC(); 

    PC *GetPC(); 

private:
    PC *m_PC; 
};

void IBMBuilder:: ProduceCPU(){
    string brand;
    double frequency;
    cin>>brand>> frequency;
    cin.get();

    HardWare* wcpu = new CPU(brand, frequency);
    m_PC->AddToPC(wcpu);

    delete wcpu;
}

void IBMBuilder:: ProduceHardDisk(){
    string brand;
    unsigned int store;
    cin>>brand>> store;
    cin.get();

    HardWare *wdisk = new HardDisk(brand, store);
    m_PC->AddToPC(wdisk);

    delete wdisk;
}

void IBMBuilder:: ProduceMainBoard(){
    string brand, type;
    cin >> brand >> type;
    cin.get();

    HardWare *wboard = new MainBoard(brand, type);
    m_PC->AddToPC(wboard);

    delete wboard;
}

void IBMBuilder:: ProducePC(){
    m_PC = new PC();
}

PC * IBMBuilder:: GetPC(){
    return m_PC;
}


int main()
{
    cout << "\nBuilding Dell Computer\n";

    Builder *pDell = new DellBuilder(); 
    pDell->ProducePC();                 
    pDell->ProduceCPU();               
    pDell->ProduceHardDisk();           
    pDell->ProduceMainBoard();          
    pDell->GetPC()->Work();             

    cout << "\nBuilding IBM Computer\n";

    IBMBuilder *pIBM = new IBMBuilder();
    pIBM->ProducePC();
    pIBM->ProduceCPU();
    pIBM->ProduceHardDisk();
    pIBM->ProduceMainBoard();
    pIBM->GetPC()->Work();

    system("pause");
    return 0;
}

类关系图
HardWare.png

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

简单 2022-09-19 02:43:41

C++ 看起来比较吃力,不过在 DellBuilder::ProduceCPU() 中有这么几句

HardWare* wcpu = new CPU(brand, frequency);
m_PC->AddToPC(wcpu);
delete wcpu;

wcpu 被创建出来,然后就被删掉了。AddToPC 调用了 computer.push_back(obj),它添加的是一个指针,该指针指向一个 CPU 对象。

然而 delete wcpu 掉之后,computer 中的那个指针就成了一个野指针,没有指向有效的对象,再使用它的时候就肯定会出错(实体都没删了,还能干啥呢?)。

代码没仔细看下去,不过,相信还有类似的问题。

那该什么时候删?

一般原则是哪里创建哪些删,但这个原则对构造,Builder,Factory 等构建类方法不适用,因为东西才创造出来,还没用呢,你就删,还怎么用呢?

理论上来说,DellBuilder 应该创建一个 pDellPc(GetPC())。
pDellBuilder 用完之后可以 delete pDellBuilder 删除掉,但它创建出来的 pDellPc 不能删。它应该在用完之后通过 delete pDellPc 来删除掉。接下来,PC 中的硬件由于不需要离开 PC 单独使用,所以在 PC 的析构函数中删除掉。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文