Bruce ekel 的《Thinking in C++》中,给出了一个关于友元函数的示例
// Declaration (incomplete type specification):
struct X;
struct Y {
void f(X*);
};
struct X { // Definition
private:
int i;
public:
friend void Y::f(X*); // Struct member friend
};
void Y::f(X* x) {
x->i = 47;
}
现在他解释了这一点:
注意 Y::f(X*) 获取 X 的地址 目的。这很重要,因为编译器总是知道如何 传递一个地址,无论对象如何,该地址都是固定大小的 被传递,即使它没有有关大小的完整信息 的类型。但是,如果您尝试传递整个对象, 编译器必须查看 X 的整个结构体定义,才能知道 大小以及如何在允许您声明函数之前传递它 例如 Y::g(X)。
但是当我尝试
void f(X);
作为结构体Y中的声明,它没有显示错误。 请解释一下为什么?
函数声明的参数类型可能不完整。
对于数据成员声明和所有定义,类型必须完整:
struct A;
struct B {
void f(A); // declaration, fine
void g(A) {} // error
A a; // error
};
按值传递不完整对象
X
应该没问题,但在函数实现期间,无论X
类型的对象是否实际在函数中使用,完整类型X
都必须可用。
函数声明可以使用不完整的对象作为参数或返回类型,但协变返回类型(对于成员函数)除外,其中此类返回类型必须是完整类型。
问题是当您更改结构 X 中的声明时。
因此,在 struct X 内部,您告诉编译器该结构体有一个接收 X 类型内容的函数,但是等一下,此时类型 X 尚未完全定义!
您不能使用不完整类型作为函数 f 的参数,但可以使用不完整类型的地址,即 X*。