C++ c++;为什么这个前瞻性声明失败了?

C++ c++;为什么这个前瞻性声明失败了?,c++,C++,我有一节课,内容如下 class Book; //forward declaration of Book class Reader { public: Reader(); void SetBook( Book ); private: Book book_; // Error Reader::book_ uses undefined class Book } 和.cpp包含 #include "book.h" void Reader::SetBook( Bo

我有一节课,内容如下

class Book; //forward declaration of Book

class Reader
{
public:
    Reader();

    void SetBook( Book ); 

private:

    Book book_; // Error Reader::book_ uses undefined class Book

}
和.cpp包含

#include "book.h"

void Reader::SetBook( Book book ) { this->book_ = book; }
// Error C2440 cannot convert from Book to int
我不明白为什么这个前瞻性声明不起作用。 此外,它不会为声明中使用的“Book”类型抛出错误

void SetBook (Book )

有什么问题吗?

声明指针或引用时,向前声明就足够了。因为您的成员
book
属于book类型,所以编译器在处理头文件时需要定义
book

头文件
book
中的是一个不完整的类型(编译器知道它是一个类型,但不知道它有多大,也不知道它的成员是什么)

可以使用类型不完整的参数声明函数(
SetBook
),但要声明成员变量(
book
),类型需要完整(完全声明)。特别是,编译器需要知道
图书
有多大,以便决定
阅读器
有多大


一个解决方案是将
book\uuuu
变成一个智能指针(您可以将它变成一个原始指针,但为什么要创建所有内存处理难题呢?)。然后编译器知道它需要一个指针(并且不关心指向的对象有多大)。

这里有一个完全非正式的替代方法来查看它:

如果你只是在写标签,上面写着“一罐蜂蜜”,你只需要知道如何拼写它

现在,如果你想把标签贴在罐子上,带回家吃,你需要知道这个该死的罐子是什么样子以及如何打开它


以下是转发声明或定义问题的经验法则:

转发声明是标签,定义意味着打开该框。

是否正在使用类型的内部信息(即大小、内存布局、成员数据/函数),或仅使用其名称

class Book; // forward declaration of Book. Right now we know nothing about Book's internal info except it's unique ID, i.e. the name of type: Book.  
Book *ptr;  // OK, pointer's size is fixed and it has nothing to do with Book.
Book **pptr; // Ok, same with previous    
ptr->someDataMember = bla; // ERROR, we don't know what is in a Book object.  
ptr->callDataFunc();       // ERROR
++ptr;  // ERROR, need to know the sizeof Book, since ++ptr equals to (char*)ptr + sizeof(Book)  
++pptr; // OK
*pptr++; // OK, *pptr is a Book*, which size is fixed.
**pptr++; // ERROR    

template<typename T>
class DontUseT{};
DontUseT<Book> dut;  // OK, we don't use Book's internal information here

int foo(Book *b) { return sizeof(b);}  // OK  
int foo(Book&b) { return 0;}  // OK  
int foo(Book&b) { return sizeof(Book);}  // ERROR
int foo(Book);   // OK  
int foo(Book) {} // ERROR, inside the definition it's supposed to access its arguments     
课程手册;//书的转发声明。现在我们对图书的内部信息一无所知,只知道它的唯一ID,即类型名称:Book。
书籍*ptr;//好的,指针的大小是固定的,它和书本无关。
书籍**pptr;//好的,和前面的一样
ptr->someDataMember=bla;//错误,我们不知道Book对象中有什么。
ptr->callDataFunc();//错误
++ptr;//错误,需要知道书本的大小,因为++ptr等于(char*)ptr+sizeof(Book)
++pptr;//好啊
*pptr++;//好的,*pptr是一本书*,大小是固定的。
**pptr++;//错误
样板
类DontUseT{};
DontUseT dut;//好的,我们这里不使用这本书的内部信息
intfoo(Book*b){returnsizeof(b);}//OK
int foo(Book&b){return 0;}//OK
intfoo(Book&b){returnsizeof(Book);}//错误
int foo(书籍);//好啊
int foo(Book){}//ERROR,在定义中它应该访问其参数

请点击此链接,这将很有帮助。