2009-04-30 94 views

回答

12

因为声明一个类型,它的大小需要知道。您可以转发声明指向该类型的指针,或者typedef指向该类型的指针。

如果你真的想,你可以使用pimpl成语来保持包含。但是如果你想使用类型而不是指针,编译器必须知道它的大小。

编辑:j_random_hacker增加了一个重要的先决条件这个答案,基本上是大小必须知道使用类型,但可以进行预先声明,如果我们只需要知道存在类型,在为了创建类型的指针或引用。由于OP没有显示代码,但抱怨说它不会编译,我假设(可能是正确的)OP正在尝试使用类型,而不仅仅是指它。

+30

嗯,类类型的前置声明没有他们的大小的知识声明这些类型。另外,除了能够定义指向这些不完整类型的指针和引用之外,还可以声明(但未定义)函数,它们接受参数和/或返回这些类型的值。 – 2009-04-30 07:47:44

+3

对不起,我认为这不是一个好的假设。这个答案就在这一点上。 typedef是前向声明的例子。 – Cookie 2011-07-22 16:27:09

143

你可以做forward forward typedef。但要做到

typedef A B; 

必须先向前声明A

class A; 

typedef A B; 
+8

最后+1,因为虽然你在技术上不能“转发typedef”(即你不能写“typedef A;”),但你几乎可以肯定地完成OP使用上述技巧完成的任务。 – 2009-04-30 07:30:20

+8

但请注意,如果typedef发生更改,您可能也会更改所有这些前向声明,如果旧的和新的typedef使用具有相同接口的类型,则可能会错过。 – math 2011-01-27 16:34:54

15

在C++(而不是普通的C),这是完全合法的typedef定义一个类型的两倍,因此只要这两个定义是完全相同:

// 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); 
41

对于那些你喜欢我,谁正在寻找转发声明使用typede定义的C型结构男,在一些C++代码,我发现,去如下的解决方案......

// a.h 
typedef struct _bah { 
    int a; 
    int b; 
} bah; 

// b.h 
struct _bah; 
typedef _bah bah; 

class foo { 
    foo(bah * b); 
    foo(bah b); 
    bah * mBah; 
}; 

// b.cpp 
#include "b.h" 
#include "a.h" 

foo::foo(bah * b) { 
    mBah = b; 
} 

foo::foo(bah b) { 
    mBah = &b; 
} 
10

要“FWD声明的typedef”你需要FWD声明一个类或结构,然后你可以的typedef声明的类型。编译器可以接受多个相同的typedef。

长型:

class MyClass; 
typedef MyClass myclass_t; 

简称:

typedef class MyClass myclass_t; 
6

使用前置声明的完整#include!而非可能只有当你打算使用该类型本身(在这个文件的作用域中),而是指向它的指针或引用。

要使用类型本身,编译器必须知道它的大小 - 因此必须看到它的完整声明 - 因此需要完整的#include

但是,无论指针的大小如何,指针或引用的大小都是编译器已知的,所以前向声明就足够了 - 它声明了一个类型标识符名称。

有趣的是,使用指针或引用classstruct类型时,编译器可以处理不完全类型节省您需要转发声明指针对象类型以及:

// header.h 

// Look Ma! No forward declarations! 
typedef class A* APtr; // class A is an incomplete type - no fwd. decl. anywhere 
typedef class A& ARef; 

typedef struct B* BPtr; // struct B is an incomplete type - no fwd. decl. anywhere 
typedef struct B& BRef; 

// Using the name without the class/struct specifier requires fwd. decl. the type itself.  
class C;   // fwd. decl. type 
typedef C* CPtr; // no class/struct specifier 
typedef C& CRef; // no class/struct specifier 

struct D;  // fwd. decl. type 
typedef D* DPtr; // no class/struct specifier 
typedef D& DRef; // no class/struct specifier 
1

我有同样的问题,不想在不同的文件类型定义多乱七八糟的,所以我继承解决它:

是:

class BurstBoss { 

public: 

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

做:

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 
0

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