为什么编译器不让我向前声明类型定义?
假设这是不可能的,那么保持我的包含树小的最佳实践是什么?
为什么编译器不让我向前声明类型定义?
假设这是不可能的,那么保持我的包含树小的最佳实践是什么?
当前回答
要“fwd声明一个类型定义”,你需要fwd声明一个类或结构,然后你可以typedef声明类型。编译器可以接受多个相同的类型。
长形式:
class MyClass;
typedef MyClass myclass_t;
简式:
typedef class MyClass myclass_t;
其他回答
在c++(而不是普通C)中,对一个类型定义两次是完全合法的,只要两个定义完全相同:
// foo.h
struct A{};
typedef A *PA;
// bar.h
struct A; // forward declare A
typedef A *PA;
void func(PA x);
// baz.cc
#include "bar.h"
#include "foo.h"
// We've now included the definition for PA twice, but it's ok since they're the same
...
A x;
func(&x);
另一个解决方案是将forward声明和typedefs放在一个单独的头文件中,并包括:
// ForwardDeclarations.h
#pragma once
namespace Foo
{
struct Bar;
typedef Bar Baz;
}
// SomeFile.h
#include "ForwardDeclarations.h"
Foo::Baz baz;
当然,这实际上并没有减少要包含的文件数量,编译器仍然必须从磁盘读取这个文件,但至少内容比完整的定义更简单。您可以在同一个文件中添加更多的前向声明,并将其包含在相关位置。
你可以使用正向类型定义。但是要做
typedef A B;
你必须先向前申报A:
class A;
typedef A B;
正如Bill Kotsias所指出的,保持点的typedef细节为私有并向前声明的唯一合理方法是继承。不过,使用c++ 11可以做得更好一些。考虑一下:
// LibraryPublicHeader.h
class Implementation;
class Library
{
...
private:
Implementation* impl;
};
// LibraryPrivateImplementation.cpp
// This annoyingly does not work:
//
// typedef std::shared_ptr<Foo> Implementation;
// However this does, and is almost as good.
class Implementation : public std::shared_ptr<Foo>
{
public:
// C++11 allows us to easily copy all the constructors.
using shared_ptr::shared_ptr;
};
因为要声明一个类型,就需要知道它的大小。可以前向声明指向该类型的指针,也可以对指向该类型的指针进行类型定义。
如果您真的想这样做,您可以使用pimpl习语来减少包含。但是如果你想使用类型,而不是指针,编译器必须知道它的大小。
Edit: j_random_hacker为这个答案添加了一个重要的限定条件,基本上是需要知道该类型的大小才能使用该类型,但是如果我们只需要知道该类型的存在,就可以进行前向声明,以便创建指向该类型的指针或引用。由于OP没有显示代码,但抱怨它不会编译,我假设(可能是正确的)OP试图使用类型,而不仅仅是引用它。