尝试实现访问者设计模式时编译器错误

时间:2018-01-26 08:14:37

标签: c++ design-patterns

我尝试根据培训材料中的类图实现访问者设计模式。我刚刚参加过这次培训,但我没有保存我在那里实施的代码。我陷入了编译错误,我无法弄清楚我做错了什么。很可能我并不了解这种设计模式的类图。下面我把整个代码和我收到的编译错误。

    #define _USE_MATH_DEFINES
    #include <list>
    #include "math.h"

    class Cerc;
    class Dreptunghi;
    class Arie;
    class Perimetru;
    class Operatie;

    class Forma
    {
    public:
        virtual void accept(Operatie * op);
        Forma(void){};
        ~Forma(void){};
    };

    class Cerc : public Forma {
    protected:
        int raza;
    public:
        void accept(Operatie * op){op->vizitare(this);};
        int getRaza(){return raza;};
        Cerc(void):raza(3){};
        ~Cerc(void){};
    };

    class Dreptunghi : public Forma {
    protected:
        int lungime;
        int latime;
    public:
        void accept(Operatie * op){op->vizitare(this);};
        int getLungime(void){return lungime;};
        int getLatime(void){return latime;};
        Dreptunghi(void):lungime(3),latime(3){};
        ~Dreptunghi(void){};
    };

    class Operatie{
    public:
        virtual void vizitare(Cerc* obj) = 0;
        virtual void vizitare(Dreptunghi* obj) = 0;
        Operatie(void){};
        ~Operatie(void){};
    };

    class Arie : public Operatie {
    private:
        double arie;
    public:
        double getResult(){return arie;};
        void vizitare(Cerc* obj){arie = arie + M_PI*obj->getRaza();};
        void vizitare(Dreptunghi* obj){arie = arie + obj->getLungime() + obj->getLatime();};
        Arie(void): arie(0) {};
        ~Arie(void){};
    };

    class Perimetru : public Operatie {
    private:
        double perimetru;
    public:
        double getResult(){return perimetru;};
        void vizitare(Cerc* obj){perimetru = perimetru + M_PI*obj->getRaza()*obj->getRaza();};
        void vizitare(Dreptunghi* obj){perimetru = perimetru + 2*(obj->getLungime() + obj->getLatime());};
        Perimetru(void):perimetru(0){};
        ~Perimetru(void){};
    };

    class Editor{
    private:
        std::list<Forma*> forme;
    public:
        Editor(void){};
        void insert(Forma obj){forme.insert(forme.end(), &obj);};
        double calculeazaArieTotala(){
            Arie arie;

            for(std::list<Forma *>::iterator it = forme.begin(); it != forme.end(); ++it){
                (*it)->accept(&arie);
            }

            return arie.getResult();
        };

        double calculeazaPerimetrulTotal(){
            Perimetru permietru;

            for(std::list<Forma *>::iterator it = forme.begin(); it != forme.end(); ++it){
                (*it)->accept(&permietru);
            }

            return permietru.getResult();
        };
        ~Editor(void){};
    };


    int main(void){
        Editor editor;
        cout << editor.calculeazaArieTotala() << endl;
        cout << editor.calculeazaPerimetrulTotal() << endl;
    }

我得到的编译器错误:

    visitordesignpattern.cpp(23): error C2027: use of undefined type 'Operatie'
    visitordesignpattern.cpp(23) : see declaration of 'Operatie'
    visitordesignpattern.cpp(23) error C2227: left of '->vizitare' must point to class/struct/union/generic type
    visitordesignpattern.cpp(23) error C2027: use of undefined type 'Operatie'
    visitordesignpattern.cpp(23) see declaration of 'Operatie'
    visitordesignpattern.cpp(23) error C2227: left of '->vizitare' must point to class/struct/union/generic type

谢谢!

3 个答案:

答案 0 :(得分:2)

当您撰写op->vizitare(this);时,Operatie的类型必须为complete,即之前必须显示其定义;只有前瞻性声明是不够的。

Operatie的定义移到它之前。 e.g。

... ...

class Operatie{
public:
    virtual void vizitare(Cerc* obj) = 0;
    virtual void vizitare(Dreptunghi* obj) = 0;
    Operatie(void){};
    ~Operatie(void){};
};

class Cerc : public Forma {
protected:
    int raza;
public:
    void accept(Operatie * op){op->vizitare(this);};
    int getRaza(){return raza;};
    Cerc(void):raza(3){};
    ~Cerc(void){};
};

class Dreptunghi : public Forma {
protected:
    int lungime;
    int latime;
public:
    void accept(Operatie * op){op->vizitare(this);};
    int getLungime(void){return lungime;};
    int getLatime(void){return latime;};
    Dreptunghi(void):lungime(3),latime(3){};
    ~Dreptunghi(void){};
};

... ...

答案 1 :(得分:0)

只需将Operatie的定义移到代码的开头即可。

答案 2 :(得分:0)

您的代码中有两个错误!正如 songyuanyao 所说,调整你的代码安排!第二个错误是在文件头添加iostream!完整代码如下所示

#define _USE_MATH_DEFINES
#include <list>
#include "math.h"
#include <iostream>


using namespace std;



class Dreptunghi;
class Arie;
class Perimetru;
class Operatie;
class Cerc;

class Forma
{
public:
    virtual void accept(Operatie * op);
    Forma(void){};
    ~Forma(void){};
};
class Operatie{
public:
    virtual void vizitare(Cerc* obj) = 0;
    virtual void vizitare(Dreptunghi* obj) = 0;
    Operatie(void){};
    ~Operatie(void){};
};

class Cerc : public Forma {
protected:
    int raza;
public:
    void accept(Operatie* op){op->vizitare(this);};
    int getRaza(){return raza;};
    Cerc(void):raza(3){};
    ~Cerc(void){};
};

class Dreptunghi : public Forma {
protected:
    int lungime;
    int latime;
public:
    void accept(Operatie * op){op->vizitare(this);};
    int getLungime(void){return lungime;};
    int getLatime(void){return latime;};
    Dreptunghi(void):lungime(3),latime(3){};
    ~Dreptunghi(void){};
};



class Arie : public Operatie {
private:
    double arie;
public:
    double getResult(){return arie;};
    void vizitare(Cerc* obj){arie = arie + M_PI*obj->getRaza();};
    void vizitare(Dreptunghi* obj){arie = arie + obj->getLungime() + obj->getLatime();};
    Arie(void): arie(0) {};
    ~Arie(void){};
};

class Perimetru : public Operatie {
private:
    double perimetru;
public:
    double getResult(){return perimetru;};
    void vizitare(Cerc* obj){perimetru = perimetru + M_PI*obj->getRaza()*obj->getRaza();};
    void vizitare(Dreptunghi* obj){perimetru = perimetru + 2*(obj->getLungime() + obj->getLatime());};
    Perimetru(void):perimetru(0){};
    ~Perimetru(void){};
};

class Editor{
private:
    std::list<Forma*> forme;
public:
    Editor(void){};
    void insert(Forma obj){forme.insert(forme.end(), &obj);};
    double calculeazaArieTotala(){
        Arie arie;

        for(std::list<Forma *>::iterator it = forme.begin(); it != forme.end(); ++it){
            (*it)->accept(&arie);
        }

        return arie.getResult();
    };

    double calculeazaPerimetrulTotal(){
        Perimetru permietru;

        for(std::list<Forma *>::iterator it = forme.begin(); it != forme.end(); ++it){
            (*it)->accept(&permietru);
        }

        return permietru.getResult();
    };
    ~Editor(void){};
};


int main(void){
    Editor editor;
    cout << editor.calculeazaArieTotala() << endl;
    cout << editor.calculeazaPerimetrulTotal() << endl;
}