当前位置:  开发笔记 > 编程语言 > 正文

无效使用不完整类型

如何解决《无效使用不完整类型》经验,为你挑选了2个好方法。

我正在尝试在项目中使用子类的typedef,我在下面的示例中已经分离了我的问题.

有谁知道我哪里出错了?

template
class A {
    public:
        //Why doesn't it like this?
        void action(typename Subclass::mytype var) {
            (static_cast(this))->do_action(var);
        }
};

class B : public A {
    public:
        typedef int mytype;

        B() {}

        void do_action(mytype var) {
            // Do stuff
        }
};

int main(int argc, char** argv) {
    B myInstance;
    return 0;
}

这是我得到的输出:

sean@SEAN-PC:~/Documents/LucadeStudios/experiments$ g++ -o test test.cpp
test.cpp: In instantiation of ‘A’:
test.cpp:10:   instantiated from here
test.cpp:5: error: invalid use of incomplete type ‘class B’
test.cpp:10: error: forward declaration of ‘class B’

Johannes Sch.. 63

原因是,在实例化类模板时,其成员函数的所有声明(而不是定义)也会被实例化.当需要完整定义特化时,将精确地实例化类模板.例如,在它被用作基类时就是这种情况,就像你的情况一样.

所以会发生什么A是实例化的

class B : public A

此时B还不是一个完整的类型(它是在类定义的结束括号之后).但是,A::action声明需要B完整,因为它在它的范围内爬行:

Subclass::mytype

您需要做的是将实例化延迟到B完成的某个点.这样做的一种方法是修改声明action以使其成为成员模板.

template
void action(T var) {
    (static_cast(this))->do_action(var);
}

它仍然是类型安全的,因为如果var是不正确的类型,传递vardo_action将失败.



1> Johannes Sch..:

原因是,在实例化类模板时,其成员函数的所有声明(而不是定义)也会被实例化.当需要完整定义特化时,将精确地实例化类模板.例如,在它被用作基类时就是这种情况,就像你的情况一样.

所以会发生什么A是实例化的

class B : public A

此时B还不是一个完整的类型(它是在类定义的结束括号之后).但是,A::action声明需要B完整,因为它在它的范围内爬行:

Subclass::mytype

您需要做的是将实例化延迟到B完成的某个点.这样做的一种方法是修改声明action以使其成为成员模板.

template
void action(T var) {
    (static_cast(this))->do_action(var);
}

它仍然是类型安全的,因为如果var是不正确的类型,传递vardo_action将失败.



2> Martin York..:

你可以通过使用traits类来解决这个问题:
它要求你为你使用的每个实际类设置一个特殊的traits类.

template
class SubClass_traits
{};

template
class A {
    public:
        void action(typename SubClass_traits::mytype var)
        {
                (static_cast(this))->do_action(var);
        }
};


// Definitions for B
class B;   // Forward declare

template<> // Define traits for B. So other classes can use it.
class SubClass_traits
{
    public:
        typedef int mytype;
};

// Define B
class B : public A
{
    // Define mytype in terms of the traits type.
    typedef SubClass_traits::mytype  mytype;
    public:

        B() {}

        void do_action(mytype var) {
                // Do stuff
        }
};

int main(int argc, char** argv)
{
    B myInstance;
    return 0;
} 

推荐阅读
wurtjq
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有