例如:
class B; class A { public: B f(); }; int main(int, char**) { A a; // no exception and error return 0; }
类A可能是不完整类型。为什么类A可以在这个例子中被示例化?我知道当在代码中调用成员函数f时,程序将无法编译。
A
f
hgtggwj01#
在C中,实体不需要在使用它们的同一个翻译单元中定义(例外情况适用)。因此,不在一个翻译单元中定义并不意味着您不会在另一个翻译单元中定义和显式示例化成员函数。同样,在C中,也没有必要定义完全不使用ODR(例如调用)的实体。这对于自由函数也是一样的,如果你实际上是ODR使用(例如调用)一个自由函数,你也只需要定义它,并且定义只需要在一个翻译单元中。A类可以是不完全类型。定义class A { /*...*/ };后A就完成了,成员函数是否定义不影响完整性。我知道当在代码中调用成员函数f时,程序将无法编译。但是只有当所有的翻译单元都链接在一起时,它才会在链接器步骤失败,因为在此之前编译器无法知道函数没有在其他地方定义和示例化。如果函数不是ODR使用的(例如调用),那么链接器就没有理由为它寻找定义。注意,B不完整也不是问题,返回类型只需要在函数的 * definition * 中完整,而不是它的声明中完整,并且可以在另一个翻译单元中定义成员函数之前完成B。B也需要在调用函数时完成,但通常不用于其他ODR用途。这适用于所有返回和参数类型。尽管如此,B可以在不定义函数的情况下完成。这仍然可以在另一个翻译单元中发生。ODR在上面的意思是"* 一个定义规则 *"。这是一个规则,在整个程序中,一个给定的实体应该有一个确切的定义。该规则不完全适用于所有的实体,特别是模板化实体,只要定义相同,就可以在每个翻译中定义一次(确切的规则更复杂)。"ODR使用"指的是一个实体的使用,它将触发一个定义规则,要求(至少)该实体的一个定义存在于程序中的某个地方。例如,调用函数或获取函数的地址。有关详细信息,请参见https://en.cppreference.com/w/cpp/language/definition。
class A { /*...*/ };
B
bxpogfeg2#
为什么在这个例子中类A可以被示例化?因为当定义一个非静态局部变量如A a;时,要求定义的类型是一个完整类型,并且由于A在定义A a;时是完整的,它满足了这个要求。还要注意,B f();是一个声明,而不是一个定义,当 * 声明 * 一个函数/成员函数时,返回类型可以是不完整的类型,如B。
A a;
B f();
2条答案
按热度按时间hgtggwj01#
在C中,实体不需要在使用它们的同一个翻译单元中定义(例外情况适用)。因此,不在一个翻译单元中定义并不意味着您不会在另一个翻译单元中定义和显式示例化成员函数。
同样,在C中,也没有必要定义完全不使用ODR(例如调用)的实体。
这对于自由函数也是一样的,如果你实际上是ODR使用(例如调用)一个自由函数,你也只需要定义它,并且定义只需要在一个翻译单元中。
A类可以是不完全类型。
定义
class A { /*...*/ };
后A
就完成了,成员函数是否定义不影响完整性。我知道当在代码中调用成员函数f时,程序将无法编译。
但是只有当所有的翻译单元都链接在一起时,它才会在链接器步骤失败,因为在此之前编译器无法知道函数没有在其他地方定义和示例化。如果函数不是ODR使用的(例如调用),那么链接器就没有理由为它寻找定义。
注意,
B
不完整也不是问题,返回类型只需要在函数的 * definition * 中完整,而不是它的声明中完整,并且可以在另一个翻译单元中定义成员函数之前完成B
。B
也需要在调用函数时完成,但通常不用于其他ODR用途。这适用于所有返回和参数类型。尽管如此,B
可以在不定义函数的情况下完成。这仍然可以在另一个翻译单元中发生。ODR在上面的意思是"* 一个定义规则 *"。这是一个规则,在整个程序中,一个给定的实体应该有一个确切的定义。该规则不完全适用于所有的实体,特别是模板化实体,只要定义相同,就可以在每个翻译中定义一次(确切的规则更复杂)。
"ODR使用"指的是一个实体的使用,它将触发一个定义规则,要求(至少)该实体的一个定义存在于程序中的某个地方。例如,调用函数或获取函数的地址。
有关详细信息,请参见https://en.cppreference.com/w/cpp/language/definition。
bxpogfeg2#
为什么在这个例子中类A可以被示例化?
因为当定义一个非静态局部变量如
A a;
时,要求定义的类型是一个完整类型,并且由于A
在定义A a;
时是完整的,它满足了这个要求。还要注意,
B f();
是一个声明,而不是一个定义,当 * 声明 * 一个函数/成员函数时,返回类型可以是不完整的类型,如B
。