为什么编译器不让我向前声明类型定义?

假设这是不可能的,那么保持我的包含树小的最佳实践是什么?


当前回答

你可以使用正向类型定义。但是要做

typedef A B;

你必须先向前申报A:

class A;

typedef A B;

其他回答

在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);

我也有同样的问题,不想在不同的文件中混淆多个typedef,所以我用继承解决了它:

was:

class BurstBoss {

public:

    typedef std::pair<Ogre::ParticleSystem*, bool> ParticleSystem; // removed this with...

did:

class ParticleSystem : public std::pair<Ogre::ParticleSystem*, bool>
{

public:

    ParticleSystem(Ogre::ParticleSystem* system, bool enabled) : std::pair<Ogre::ParticleSystem*, bool>(system, enabled) {
    };
};

效果很好。当然,我必须改变所有的参考资料

BurstBoss::ParticleSystem

简单地

ParticleSystem

另一个解决方案是将forward声明和typedefs放在一个单独的头文件中,并包括:

// ForwardDeclarations.h
#pragma once
namespace Foo
{
    struct Bar;
    typedef Bar Baz;
}

// SomeFile.h
#include "ForwardDeclarations.h"
Foo::Baz baz;

当然,这实际上并没有减少要包含的文件数量,编译器仍然必须从磁盘读取这个文件,但至少内容比完整的定义更简单。您可以在同一个文件中添加更多的前向声明,并将其包含在相关位置。

正如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;
};

我用继承和构造函数继承(?)替换了typedef(用来指定)。

原始

using CallStack = std::array<StackFrame, MAX_CALLSTACK_DEPTH>;

取代

struct CallStack // Not a typedef to allow forward declaration.
  : public std::array<StackFrame, MAX_CALLSTACK_DEPTH>
{
  typedef std::array<StackFrame, MAX_CALLSTACK_DEPTH> Base;
  using Base::Base;
};

通过这种方式,我可以向前声明CallStack:

class CallStack;