因为在第二份代码中,不存在对Date内部成员的依赖,即我只要知道Date是一个class的类型即可,然后我在链接的时候再去找其实际的定义之处。
而在第一份代码中,
private:
std::string theName;
Date theBirthDate;
Address theAddress;
};
这里我需要知道Date完整的声明,才能知道Date有多大。
但是你在第一第二份代码中的函数声明中的const Date& d则不需要,因为引用类型可以指向不完整的类型,而如果是Date d,则需要提供完整的类型。
虽然C++标准写了一堆条件表明了引用类型是可以指向不完整的类型,但是我想从先前的角度继续来说,那就是引用类型是编译器知道大小的,无论是何种类型都是一样。所以只要你告诉我const Date& d,或者const string& str等,我编译器在分配占用大小时,我都知道分配多少。那么,引用类型在如今我能知道的编译器当中都是使用了指针来实现,所以其占用的大小是指针大小。
class Date {
public:
Date& d;
};
int main()
{
cout << sizeof(Date) << "\n"; // 8 on 64bits
}
所以,第二份代码其实是只要知道Date是一个class类型即可,跟Date内部实现是没有任何关系的,所以Date改变了实现,第二份代码也不需要重新编译。
=============
具体原因其它答案有解答,我补充一点。
class Date;这个声明不应该与class Person的定义写在同一个文件中,而是应由
class Date 的作者提供一个datefwd.h/hpp这样的头文件。否则,还是直接包含date.h/hpp这个
头文件比较适合。
原因如下:1.做为使用者,你实际不知道,也不应知道Date是class或struct还是class template , template alias. 当不确认是否能直接这个优化时,不如直接依赖引入date.h。
2.在我的实践中,当Date是有参数的类模板,无法写出与原定义兼容的前置声明。如果我错了,请指正。
所以,这个条目是一个优化,但不是一个普遍且必需的优化。