使用返回不完整类型的函数作为默认参数

Use function returning incomplete type as default argument

当我尝试编译 运行 这段代码时(只有前三行才是真正重要的):

class object;
object getObject();
void doSomething(object o = getObject());

class object{
    public:
        int num = 0;
};

object getObject(){
    return {};
}

void doSomething(object o){
    o.num = 5;
}

int main(){}

我收到这个错误:

main.cpp:3:39: error: invalid use of incomplete type 'class object'
 void doSomething(object o = getObject());
                                       ^
main.cpp:1:7: note: forward declaration of 'class object'
 class object;
       ^

如何在不改变所有顺序的情况下编译它?在我的实际代码中,声明放在一起,而定义分布在多个文件中。是否可以在不分离声明的情况下解决问题?

为什么现阶段类型不完整很重要?

在错误点,对象已经被前向声明,但是他的定义还没有到达,所以对象是一个不完整的类型。你只能有不完整类型的指针。

你需要像这样的完整定义

class object{
    public:
        int num = 0;
};

object getObject();
void doSomething(object o = getObject());

object getObject(){
    return {};
}

void doSomething(object o){
    o.num = 5;
}

int main(){}

或者如果您不想重新排序,则必须通过指针传递所有内容

class object;
object* getObject();
void doSomething(object* o = getObject());

class object{
    public:
        int num = 0;
};

object* getObject(){
    return new object();
}

void doSomething(object* o){
    o->num = 5;
    delete o;
}

int main(){}

但第一个解决方案确实更好

How would I get it to compile without changing the order of everything?

您不必更改 所有内容 的顺序,但您确实需要更改 某些内容 的顺序。特别是,必须在调用 getObject 之前定义 object(在默认参数表达式中)。

Is it possible to do solve without separating the declarations?

有点不清楚这意味着什么,但如果您在顶部定义 object,则声明可以与示例中的完全一样。

另一种选择是在 object 定义后使用默认参数重新声明函数:

class object;
object getObject();
void doSomething(object o);

class object{
    public:
        int num = 0;
};

void doSomething(object o = getObject());

这当然意味着第一次声明之后但重新声明之前的代码不会受益于默认参数。

最后,有点技巧。在实例化模板之前,模板中的表达式不需要完整,因此如果 doSomething 是一个函数模板,您的示例就可以正常工作:

template<class T=void>
void doSomething(object o = getObject());

class object{};

object getObject(){
    return {};
}

template<class T>
void doSomething(object o){}

当然,您不应该为了解决这个问题而制作模板,但这是您在编写模板时需要注意的一个方便的细节。