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

Posted

技术标签:

【中文标题】使用返回不完整类型的函数作为默认参数【英文标题】:Use function returning incomplete type as default argument 【发布时间】:2018-12-10 20:39:24 【问题描述】:

当我尝试编译和运行这段代码时(只有前三行很重要):

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;
       ^

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

在这个阶段如果类型不完整有什么关系?

【问题讨论】:

@demogorgon.net 读取语言标签。 C++ 允许这样的语法。 new object() 将是 object *,而不是 object @Ptaq666 你可以声明一个带有不完整类型的对象参数的函数。您只是不能调用返回不完整类型的对象(或具有不完整类型的参数)的函数。这里的问题是默认参数表达式是对此类函数的调用。 @user2079303 为什么在这个阶段调用函数?我的困惑是为什么 C++ 在使用 doSomething() 之前需要有一个完整的类型。内存分配了吗? @user2079303,没错,我删除了我的评论。 @user4913118 getObject() 是一个函数调用表达式。这里的所有都是它的。语言规则根本不允许它在 getObject 的返回类型完成之前出现。 【参考方案1】:

如何在不改变所有顺序的情况下编译它?

您不必更改 everything 的顺序,但您需要更改 something 的顺序。特别是,object 必须在调用 getObject 之前定义(在默认参数表达式中)。

是否可以在不分离声明的情况下解决问题?

有点不清楚这意味着什么,但如果您在顶部定义 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)

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

【讨论】:

【参考方案2】:

在发生错误时,对象已被前向声明,但尚未达到其定义的 bean,因此对象是不完整的类型。你只能有不完整类型的指针。

你需要有这样的完整定义

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()

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

【讨论】:

以上是关于使用返回不完整类型的函数作为默认参数的主要内容,如果未能解决你的问题,请参考以下文章

作为函数参数和返回值的不完整类型

作为默认模板参数的具体函数

python函数使用参数技巧笔记

Typescript构造函数和继承

重载函数和默认参数的函数

Python 可变类型作为函数默认参数时的副作用