访问者模式编译错误C2027:使用未定义类型Visitor求助
解决C2027:访问者模式中"使用未定义类型'Visitor'"编译错误
问题场景
学习访问者模式时编写代码,出现**Error C2027 use of undefined type 'Visitor'**编译错误。代码中Cat类包含name和age属性,AgeVisitor、NameVisitor继承Visitor接口分别输出猫咪年龄和名称,已尝试前向声明Visitor但问题依旧。
原代码
#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); }
错误信息
Error C2027 use of undefined type 'Visitor',位于第18行
问题原因
前向声明class Visitor;仅告知编译器存在Visitor类,但编译器此时不知道该类的具体成员(比如visit函数)。在Cat类的Accept函数内部调用visitor->visit(this)时,需要Visitor类的完整定义才能确认visit函数的存在及签名,否则会触发未定义类型错误。
修复方案
将Cat::Accept函数的实现移到Visitor类完整定义之后,也就是类外实现。修改后的代码如下:
#include <iostream> using namespace std; // 前向声明 class Visitor; class Cat { public: Cat(string name, int age) : name_(name), age_(age) {} void Speak() { cout << "meow" << endl; } // 仅声明Accept函数 void Accept(Visitor* visitor); 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; } }; // 在Visitor类定义后实现Accept函数 void Cat::Accept(Visitor* visitor) { cout << "use implementation of visitor" << endl; visitor->visit(this); } int main() { Cat* first_cat = new Cat{ "kitty", 5 }; Visitor* age_visitor = new AgeVisitor(); first_cat->Accept(age_visitor); // 释放内存避免泄漏 delete first_cat; delete age_visitor; return 0; }
补充说明
- 类的前向声明只能用于声明指针、引用,或者作为函数参数/返回值的类型,但不能用于访问类的成员函数或成员变量。
- 访问者模式中,元素类(如
Cat)和访问者类(如Visitor)存在循环依赖,通常通过类的前向声明+类外实现成员函数的方式解决。
内容的提问来源于stack exchange,提问作者백승호
相关产品推荐
相关产品推荐

