c++ 访问者模式错误(使用未定义的类型)

a0x5cqrl  于 2023-02-06  发布在  其他
关注(0)|答案(2)|浏览(151)

我正在研究访问模式,但是出现了如下错误,未定义,cat类只有自己的name和age,agevisitor和namevisitor继承了Visitor接口,输出age和name。
我尝试了正向声明,但C2027的错误显示为它是。帮助我:(
那是我准则

#include <iostream>
using namespace std;

class Visitor;

class Cat
{
public:
    Cat(string name, int age) : name_(name), age_(age) {}

    void Speak() {
        cout << "meow" << endl;
    }

    void Accept(Visitor* visitor) {
        cout << "use implementation of visitor" << endl;
        visitor->visit(this); // #undefined type error
    }

public:
    string name_;
    int age_;

public:
    friend class AgeVisitor;
    friend class NameVisitor;
};

class Visitor
{
public:
    virtual void visit(Cat* cat) {}
};

class AgeVisitor : public Visitor
{
public:
    virtual void visit(Cat* cat) {
        cout << "cat is " << cat->age_ << "years old" << endl;
    }
};

class NameVisitor : public Visitor
{
public:
    virtual void visit(Cat* cat) {
        cout << "cat's name is " << cat->name_ << endl;
    }
};

int main()
{
    Cat* first_cat = new Cat{ "kitty", 5 };
    
    Visitor* age_visitor = new AgeVisitor();
    first_cat->Accept(age_visitor);
}

严重性代码说明项目文件行禁止显示状态错误C2027使用未定义类型'Visitor' DesignPattern C:\Users\sueng\source\repos\DesignPattern\DesignPattern. cpp 18

pcww981p

pcww981p1#

在循环依赖的情况下,比如访问者模式,理想情况下你应该先把代码分解成头文件和源文件,这是因为forward declared类有不完整的类型,所以你可以使用指针和对它们的引用,你也可以把它们用作返回类型,但是你不能使用它们的任何方法,或者在堆栈上或者动态地创建一个实际的示例。因为当时不知道类布局。
示例Cat.hpp

class Visitor;
class AgeVisitor;  // needed just for the friend declaration
class NamedVisitor;
class Cat
{
public:
    Cat(string name, int age);
    void Accept(Visitor* visitor);  // note that we only declare the class Cat, no methods definitions

public:
    string name_;
    int age_;

public:
    friend class AgeVisitor;
    friend class NameVisitor;
};

然后Visitor.h,在NamedVisitor.h等情况下类似:

class Cat;
class Visitor
{
public:
    virtual void visit(Cat* cat);
};

然后在Cat.cpp中,您可以在访问者定义中包含头文件,这允许您使用他们的方法:

#include "Cat.hpp"
#include "Visitor.hpp"

Cat::Cat(string name, int age): name_(name), age_(age) {}

void Cat::Accept(Visitor* visitor) {
    cout << "use implementation of visitor" << endl;
    visitor->visit(this);  // now you can use it, because Visitor class declaration is available
}

或者你可以复制粘贴所有的代码在您的main.cpp的顺序,但这是一个坏习惯。Live demo与一切复制粘贴在一个源代码。

qlvxas9a

qlvxas9a2#

向前声明一个类而不声明它的方法只允许在不需要类的方法信息的地方使用类名。如果你使用方法(即使是隐式的,比如调用局部变量的构造函数),你也需要向前声明它们。例如,下面的代码将无法编译:

class A;

class B
{
public:
    B();
};

class C
{
public:
    void Run()
    {
        A* pa; // ok, forward class declaration is enough to declare pointers
        A a;   // compile error, since here we call ctor, but we haven't declared it
        B b;   // ok, we declared ctor
    }
};

// can be in a different file
B::B()
{}

相关问题