我有一个包含以下内容的类.h
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 )
有什么建议吗?在这里?
答案 0 :(得分:6)
声明指针或引用时,前向声明就足够了。由于您的成员book_
属于Book类型,因此编译器在处理标题时需要Book
的定义。
答案 1 :(得分:2)
在头文件中Book
是不完整类型(编译器知道它是一种类型,但不知道它有多大,或者它的成员是什么)。
可以使用不完整类型的参数声明函数(SetBook
),但要声明成员变量(book_
),类型需要完整(完全声明)。特别是,编译器需要知道Book
有多大,以便它可以决定Reader
的大小。
一种解决方案是让book_
成为一个智能指针(你可以把它变成一个原始指针,但为什么要创建所有的内存处理头疼?)。然后编译器知道它需要一个指针(并不关心指向对象的大小)。
答案 2 :(得分:0)
以下是另一种非正式的方式:
如果你只是在写“Pot of Honey”的标签,你只需要知道如何拼写。
现在,如果你想把标签贴在锅上并带回家吃它,你需要知道这个罐子是什么样子以及如何打开它
答案 3 :(得分:0)
这是关于前向声明或定义问题的经验法则:
前向声明是标签,定义意味着打开框。
是否正在使用该类型的内部信息(即大小,内存布局,成员数据/功能),或仅使用其名称
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