代码之家  ›  专栏  ›  技术社区  ›  MilanMarkovicDrmr

循环声明和循环引用

  •  -2
  • MilanMarkovicDrmr  · 技术社区  · 9 年前

    我在这段代码中遇到了问题,它将评估数值运算。我试着搜索,但似乎没有答案。

    表示操作的基类是:

    操作说明:

    #pragma once
    #include <iostream>
    using namespace std;
    
    class Operacija
    {
    protected:
        char* naziv;
        int drugiO;
        Operacija* suprotna;
    public:
        Operacija* retOp() { return this->suprotna; }
        int retD() { return this->drugiO; }
        void printOp()
        {
            cout << "Ime operacije: " << this->naziv << endl;
            cout << "Drugi operand: " << this->drugiO << endl;
            cout << "Ime suprotne operacije: " << this->suprotna->naziv << endl;
        }
        virtual int DoOperation(int op1, int op2) = 0;
    };
    

    此派生类用于乘法:

    锰含量:

    //this is .h for 1st class
    #pragma once
    #include "Operacija.h"
    #include "Deljenje.h"
    
    class Mnozenje : public Operacija
    {
    public:
        Mnozenje(int b);
        int DoOperation(int op1, int op2);
    };
    

    Mnozenje.cpp:

    #include "Deljenje.h"
    #include "Mnozenje.h"
    class Deljenje;
    Mnozenje::Mnozenje(int b)
    {
        Deljenje* a = new Deljenje(b);
        naziv = "Mnozenje";
        suprotna = a;
        if (b == 0)
        {
            cout << "operand ne sme biti 0, stoga je stavljen na ";
            cout << "default tj. postavljen na vrednost 1!" << endl;
            drugiO = 1;
        }
        else
            drugiO = b;
    }
    
    int Mnozenje::DoOperation(int op1, int op2)
    {
        int a = 0;
        a = op1 * op2;
        return a;
    }
    

    这个派生类用于除法:

    Deljenje.h:

    #pragma once
    #include "Operacija.h"
    #include "Mnozenje.h"
    
    
    class Deljenje : public Operacija
    {
    public:
        Deljenje(int a);
        int DoOperation(int op1, int op2);
    };
    

    Deljenje.cpp:

    #include "Deljenje.h"
    #include "Mnozenje.h"
    class Mnozenje;  
    
    Deljenje::Deljenje(int a)
    {
        Mnozenje* b = new Mnozenje(a);
        naziv = "Deljenje";
        suprotna = b;
        if (a == 0)
        {
            cout << "operand ne sme biti 0, stoga je stavljen na default tj.     postavljen na vrednost 1!" << endl;
            drugiO = 1;
        }
        else
            drugiO = a;
    }
    
    int Deljenje::DoOperation(int op1, int op2)
    {
        int a = 0;
        a = op1 / op2;
        return a;
    }
    

    我确实理解为什么这不起作用,我确实尝试过只声明指针而不是初始化 suprotna 的成员 Mnozenje Deljenje 。但我有另一个类是一个数组类型的容器 Operacija 我不能有未初始化的指针,因为我需要使用 苏普鲁特纳 .

    2 回复  |  直到 9 年前
        1
  •  2
  •   Christophe    9 年前

    您的问题提出了三个问题:

    • 第一个是由于不必要的循环引用导致的编译错误。执行的答案 NO-NAME(人名) 完全解决这个问题 demonstrated here .

    • 第二种是每次创建 Mnozenje Deljene :例如,如果创建 Mnozenje公司 来自 int ,然后您将在其构建开始时创建一个新对象 Deljenje 这将在其建造之初创造一个新的 Mnozenje公司 ,这将产生……直到出现堆栈流。

    • 第三个问题是继承的预期用途。有容器的 Operacija 而不是 Operacija* 将导致 slicing 它注定会失败。

    建议:

    我明白 Mnozenje公司 是乘法和 Deljene公司 一个部门 suprotna 反向操作。

    因此,我建议您预见一个带有可选参数的构造函数,以便在创建反向操作时,可以将原始操作指示为反向。

    想法大致如下:

    class Mnozenje : public Operacija
    {
    public:
        Mnozenje(int b, Operacija* rev=nullptr);
        int DoOperation(int op1, int op2);
    };
    
    Mnozenje::Mnozenje(int b, Operacija* rev)
    {
        naziv = "Mnozenje";
        suprotna = rev==nullptr ? new Deljenje(b, this) : rev;   
        ...
    }
    
    // and the same kind of change for Deljenje
    

    在这种情况下,您将在相关对象之间创建循环引用,而不是永远递归。

    注意: 这项工作将使对象的破坏稍微复杂一些。如果你有足够的时间考试,可以考虑改变设计:

    • 为反向操作保留两个指针:一个用于新分配的对象,一个用于指向原始操作。在这种情况下,您可以使用 shared_ptr weak_ptr 帮助您管理内存;
    • 或仅在需要时创建反向操作(即,不是在构造时,而是作为成员函数的结果);
    • 或在数据结构中将操作与操作数解耦;
    • 或通过添加 UndoOperation() 成员函数。
        2
  •  1
  •   Community George Stocker    7 年前

    你不需要 #include "Mnozenje.h" 在里面 Deljenje.h #include "Deljenje.h" 在里面 Mnozenje.h 。事实上,您正在使用 .cpp 文件并不意味着必须在 .hpp 文件

    您也不需要编写这样的类声明: class Deljenje; ,因为包括(例如。 #包括“Deljenje.h” )提供了这些类的定义。

    似乎不太清楚如何包含作品。 这很简单。只包括将整个指定文件复制到 #include 指令。您可以在此处阅读更多信息: How does the compilation/linking process work?