首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模板和转发声明

模板和转发声明
EN

Stack Overflow用户
提问于 2014-08-07 18:02:32
回答 2查看 130关注 0票数 0
代码语言:javascript
复制
class VisitorBase;

template<typename R = void>
class BaseVisitable
{
public:
    typedef R RetType;
    virtual ~BaseVisitable() {}

    // Ok,only need forward-declaration of VisitorBase
    virtual R Accept(VisitorBase&) = 0; 
protected:
    template<typename T>
    static RetType AcceptImp(T& visited, VisitorBase& guest) // same as above
    {
        // there is neither forward-declaration nor definition of Visitor type,
        // how can it pass compilation?
        if (Visitor<T>* p = dynamic_cast<Visitor<T>*>(&guest)) 
        {
            return p->Visit(visited);
        }

        // Visitor<int> v; error
    }
};

这段代码摘录自LOKI.And,我在上面的注释中写了一些令人费解的东西,我不明白为什么Vistor指针不需要转发声明,而需要对象need.Thanks。

EN

回答 2

Stack Overflow用户

发布于 2014-08-07 18:46:04

Visitor<T>的正向声明是不够的,因为Visitor<T>的方法是由p->Visit(visited)调用的,这意味着在同一文件中必须通过include语句或Visitor<T>定义来声明Visitor<T>。否则,编译器就不知道Visitor<T>有一个成员Visit()

票数 0
EN

Stack Overflow用户

发布于 2014-08-07 19:02:51

我假设您的摘录来自文件Visitor.h。如果在该文件中包含的转发声明template<class T> class Visitor;,则可以编译该摘录。

Visitor模板的正向声明足以调用Visitor<T>上的函数,因为它是依赖类型,AcceptImp模板的实例化最终会实例化具有给定类型的Visitor<T>模板。到那时,必须已经定义了Visitor<T> (并且该定义还必须具有被调用的函数)。如果不是,则会出现编译时错误。如果AcceptImp模板根本没有实例化,则不会出现错误。

Visitor<int>不是依赖类型,因此必须在定义AcceptImp时定义它,而不是在定义它时定义它。由于未定义Visitor,因此无法实例化Visitor<int>

下面是一个简化的演示:

代码语言:javascript
复制
// forward declaration
template<class S>
struct Foo;

template<class T> 
void test(Foo<T>* f = nullptr) { // declaring a pointer is just fine
    if(f != nullptr)
        f->bar(); // calling a function is fine unless Foo<T> is incomplete or doesn't define bar
    // Foo<int> i; // oops, incomplete type, cannot do
    Foo<T> t; // Foo<T> must be complete when test<T> is instantiated, otherwise fails
}

// here's an example of what you can do
// let's define a specialization
template<>
struct Foo<int> {
    void bar(){}; // if we didn't define this, then we couldn't instantiate test<int>
};

// now you can instantiate Foo<int> and call test
int main() {
    Foo<int> i; // Foo<int> is a complete type now :)
    test(&i);
    // test<float>(); // oops, Foo<float> is incomplete
    //         test can't call Foo<float>::bar
    //         or instantiate an object of type Foo<float>
    //         Defining a pointer to Foo<T> in test would still be fine
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25179604

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档