正向声明模板类型参数



我看到这个问题已经在不同的地方讨论过了,比如这里,这里,这里。但是,我仍然无法理解上述问题。

我的情况:我正在尝试用C++实现一个简单的通用访问者模式。这种模式中的宿主是不同的宠物,它们在一个名为Pet.h的文件中。访问者在一个单独的标题中,名为visitors.h。

具体的Pet类accept,通用访问者类(请参见Pet.h中的注释0(,以及通用访问者类visits,即通用Pet类。因此,存在一个自然的循环依赖关系。

早些时候,当所有代码都在一个标题中时,没有任何问题。现在有了。为了说明,这里是Pet.h类。P.S:我正在使用Visual Studio 2017。

#pragma once
#include <string>
#include "Visitors.h"

namespace pet
{
class Pet {
public:
virtual ~Pet() {}
virtual void accept(temp_visitor::PetVisitor& v) = 0; //Comment 0 Pet accepts a gneric PetVisitor
virtual std::string getAnimal() = 0;
private:
std::string color_;
};
template <typename Derived>
class Visitable : public Pet {
public:
using Pet::Pet;
Visitable() = default;
Visitable(const std::string& animal) : animal_(animal) {}
void accept(temp_visitor::PetVisitor& v) override {
v.visit(static_cast<Derived*>(this));  
}
std::string getAnimal() override
{
return animal_;
}
std::string animal_;
};
class Cat : public Visitable<Cat> {
using Visitable<Cat>::Visitable;
};
class Dog : public Visitable<Dog> {
using Visitable<Dog>::Visitable;
};
}

这是Visitors.h文件。The void visit(pet::Pet* p) gives the following error "use of undefined type pet::Pet on using p->getAnimal()

#include<iostream>
#pragma once
namespace pet
{
class Pet; //Comment 1. Attempted forward declaration.
}
namespace temp_visitor
{
template <typename ... Types>
class Visitor;
template <typename T>
class Visitor<T> {
public:
virtual void visit(T* t) = 0;
};
using PetVisitor = Visitor<pet::Pet>;
class FeedingVisitor : public PetVisitor {
public:
void visit(pet::Pet* p) override { std::cout << "Feed veggies to the "+ p->getAnimal() << std::endl; }  //Comment 2: Gives the following error "use of undefined type pet::Pet"
};
}

那么我该如何解决这个问题呢?

您还需要将FeedingVisitor移动到新的标头和cpp。在标头中,您将具有#include "Visitors.h"Pet的前向清除和cpp#include "Pet.h"

类似于访问者.hpp

namespace pet  {
class Pet; //Comment 1. Attempted forward declaration.
}
namespace temp_visitor 
{
template <typename ... Types>   class Visitor;
template <typename T>  class Visitor<T> 
{
public:
virtual void visit(T* t) = 0;
};
}

FeedingVisitor.hpp

#include "Visitors.h"
namespace temp_visitor
{
using PetVisitor = Visitor<pet::Pet>;
class FeedingVisitor : public PetVisitor {
public:
void visit(pet::Pet* p) override;  // only declaration
};
}

FeedingVisitor.cpp

// move the definition to cpp
void temp_visitor::FeedingVisitor::visit(pet::Pet* p) { 
std::cout << "Feed veggies to the " + p->getAnimal() << std::endl; 
}

最新更新