0
struct X;

struct Y {
  void f(X*);
};

struct X { //definition
private:
  int i;
public:
  friend void Y::f(X*);
  <SNIP'd>
};

“structY有一个成员函数f(),可以修改类型的对象X。这有点难,因为C++ 编译器要求您在引用它之前声明所有内容Y,因此必须先声明struct,然后才能将其成员Y::f(X*)声明为struct 中的朋友X。但是Y::f(X*)要声明 structX必须先声明!

这是解决方案。请注意,它Y::f(X*)采用X对象的地址。这一点很关键,因为编译器总是知道如何传递一个地址,不管传递的对象是什么,这个地址都是固定大小的,即使它没有关于类型大小的完整信息。”

所以在这里我们有:

struct X; struct Y { ... }; struct X { ... };

我的问题是这样的:

  1. 为什么编译器坚持X不完整地声明为:struct X;??

    毕竟,正如作者所说:“编译器总是知道如何传递一个固定大小的地址。” 这只是一个声明,它告诉编译器这X是一个结构并且很快就会跟随,那么为什么编译器如此坚持要你输入字母: struct X; 毕竟我X本身没有使用??那时没有生成汇编语言代码。并且当它读取X*肯定可以说它是一个地址(指针)..为什么:struct X;需要?

    声明函数的重点是在实际使用之前进行类型检查。所以如果我这样做:

     int foo(void); foo(30); 
    

    编译器会嚎叫。但是在上面,如果我不说:struct X;它有什么区别?他只是在检查我对X(函数名)的拼写吗?

  2. 为什么颠倒结构 Y 和 X 的位置不起作用?像这样:
    struct Y; struct X { ... }; struct Y { ... };
    我得到:

    错误:不完整类型的无效使用'struct main()::Y'

    显然,编译器不满意我对 Y( struct Y;) 的类型说明不完整。但是缺少什么宝贵的小信息?毕竟 struct Y; 应该告诉编译器Y即将跟进(与我们在 Q1 中所做的相同struct X; struct Y {}; struct X{};:)

  3. 为什么作者将 structX称为定义?如果我这样做: struct X { ... };这肯定是一个声明?当我像这样实例化结构时:Xfoo; 那么这是一个定义?正确的?

  4. 我该怎么做呢:

    struct X {
      friend void Y::f(X*);
      void f(Y*);
    };
    
    struct Y {
      friend void X::f(Y*);
      void f(X*);
    };
    
4

2 回答 2

2

为什么编译器坚持将 X 不完整地声明为:struct X?? 毕竟,正如作者所说:“编译器总是知道如何传递一个固定大小的地址。”

你不这样做:这也有效:

struct Y { void f(struct X*); };

class X {
    int i;
    friend void Y::f(X*);
};

还有什么建议?

此外,在按值传递时,您甚至不必拥有完整的类型,除非您实际定义了方法

struct Y { void f(struct X); };

// too early:    
void Y::f(struct X) { /* whoops compile error */ }

class X {
    int i;
    friend void Y::f(X);
};

// ok here:
void Y::f(X) { /* compile success */ }
于 2012-06-22T10:55:18.710 回答
1

毕竟,正如作者指出的那样:“编译器总是知道如何传递一个固定大小的地址。”这只是一个声明,告诉编译器 X 是一个结构并且很快就会跟随,那么为什么编译器坚持要你打出字母:struct X;毕竟我没有使用 X 本身?那时没有生成汇编语言代码..当它读取“X *”时,它肯定可以看出它是一个地址(指针)..为什么:struct X;需要?

作者并没有告诉你所有令人讨厌的细节。编译器知道如何传递指针(地址),如果它知道对象X是什么类型的话。该语言允许某些指针char具有不同的大小,例如可寻址机器上的指针或函数指针。

因此,您必须告诉编译器这X是 astruct而不是内置类型的函数或 typedef。

于 2012-06-22T11:12:43.283 回答