C++ 中 typedef 的前向声明
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/804894/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Forward declaration of a typedef in C++
提问by user96825
Why won't the compiler let me forward declare a typedef?
为什么编译器不让我向前声明一个 typedef?
Assuming it's impossible, what's the best practice for keeping my inclusion tree small?
假设这是不可能的,保持包含树较小的最佳做法是什么?
回答by Hong Jiang
You can do forward typedef. But to do
你可以做转发typedef。但是要做
typedef A B;
you must first forward declare A
:
您必须首先转发声明A
:
class A;
typedef A B;
回答by LittleJohn
For those of you like me, who are looking to forward declare a C-style struct that was defined using typedef, in some c++ code, I have found a solution that goes as follows...
对于像我一样希望在某些 C++ 代码中声明使用 typedef 定义的 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;
}
回答by Pavel P
To "fwd declare a typedef" you need to fwd declare a class or a struct and then you can typedef declared type. Multiple identical typedefs are acceptable by compiler.
要“fwd 声明 typedef”,您需要 fwd 声明一个类或一个结构,然后您可以 typedef 声明的类型。编译器可以接受多个相同的 typedef。
long form:
长表:
class MyClass;
typedef MyClass myclass_t;
short form:
简写:
typedef class MyClass myclass_t;
回答by Adam Rosenfield
In C++ (but not plain C), it's perfectly legal to typedef a type twice, so long as both definitions are completelyidentical:
在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);
回答by tpdi
Because to declare a type, its size needs to be known. You can forward declare a pointer to the type, or typedef a pointer to the type.
因为要声明一个类型,需要知道它的大小。您可以向前声明一个指向该类型的指针,或者 typedef 一个指向该类型的指针。
If you really want to, you can use the pimpl idiom to keep the includes down. But if you want to use a type, rather than a pointer, the compiler has to know its size.
如果你真的想要,你可以使用 pimpl 成语来减少包含。但是如果你想使用一个类型而不是一个指针,编译器必须知道它的大小。
Edit: j_random_hacker adds an important qualification to this answer, basically that the size needs to be know to usethe type, but a forward declaration can be made if we only need to know the type exists, in order to create pointers or references to the type. Since the OP didn't show code, but complained it wouldn't compile, I assumed (probably correctly) that the OP was trying to usethe type, not just refer to it.
编辑:j_random_hacker 为这个答案添加了一个重要的限定,基本上需要知道大小才能使用类型,但是如果我们只需要知道类型存在,就可以进行前向声明,以便创建指向该类型的指针或引用类型。由于 OP 没有显示代码,但抱怨它无法编译,我假设(可能正确)OP 正在尝试使用该类型,而不仅仅是引用它。
回答by Adi Shavit
Using forward declarations insteadof a full #include
s is possible only when you are notintending on using the type itself (in this file's scope) but a pointer or reference to it.
仅当您不打算使用类型本身(在此文件的范围内)而是使用指向它的指针或引用时,才可以使用前向声明而不是完整的#include
s 。
To use the type itself, the compiler must know its size - hence its full declaration must be seen - hence a full #include
is needed.
要使用类型本身,编译器必须知道它的大小——因此必须看到它的完整声明——因此#include
需要一个完整的。
However, the size of a pointer or reference is known to the compiler, regardless of the size of the pointee, so a forward declaration is sufficient - it declares a type identifier name.
然而,指针或引用的大小对于编译器来说是已知的,无论指针对象的大小如何,因此前向声明就足够了——它声明了一个类型标识符名称。
Interestingly, when using pointer or reference to class
or struct
types, the compiler can handle incomplete typessaving you the need to forward declare the pointee types as well:
有趣的是,当使用指针或引用class
或struct
类型时,编译器可以处理不完整的类型,从而无需转发声明指针类型:
// 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
回答by Bill Kotsias
I had the same issue, didn't want to mess with multiple typedefs in different files, so I resolved it with inheritance:
我遇到了同样的问题,不想在不同文件中弄乱多个 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) {
};
};
Worked like a charm. Of course, I had to change any references from
像魅力一样工作。当然,我不得不改变任何引用
BurstBoss::ParticleSystem
to simply
简单地
ParticleSystem
回答by Notinlist
I replaced the typedef
(using
to be specific) with inheritance and constructor inheritance (?).
我用继承和构造函数继承(?)替换了typedef
(using
具体来说)。
Original
原来的
using CallStack = std::array<StackFrame, MAX_CALLSTACK_DEPTH>;
Replaced
已更换
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;
};
This way I was able to forward declare CallStack
with:
这样我就可以转发声明CallStack
:
class CallStack;
回答by Timmmm
As Bill Kotsias noted, the only reasonable way to keep the typedef details of your point private, and forward declare them is with inheritance. You can do it a bit nicer with C++11 though. Consider this:
正如 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;
};
回答by Mark Lakata
Like @BillKotsias, I used inheritance, and it worked for me.
像@BillKotsias 一样,我使用了继承,它对我有用。
I changed this mess (which required all the boost headers in my declaration *.h)
我改变了这个烂摊子(这需要我声明 *.h 中的所有 boost 头文件)
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/moment.hpp>
#include <boost/accumulators/statistics/min.hpp>
#include <boost/accumulators/statistics/max.hpp>
typedef boost::accumulators::accumulator_set<float,
boost::accumulators::features<
boost::accumulators::tag::median,
boost::accumulators::tag::mean,
boost::accumulators::tag::min,
boost::accumulators::tag::max
>> VanillaAccumulator_t ;
std::unique_ptr<VanillaAccumulator_t> acc;
into this declaration (*.h)
进入这个声明 (*.h)
class VanillaAccumulator;
std::unique_ptr<VanillaAccumulator> acc;
and the implementation (*.cpp) was
和实现(*.cpp)是
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/moment.hpp>
#include <boost/accumulators/statistics/min.hpp>
#include <boost/accumulators/statistics/max.hpp>
class VanillaAccumulator : public
boost::accumulators::accumulator_set<float,
boost::accumulators::features<
boost::accumulators::tag::median,
boost::accumulators::tag::mean,
boost::accumulators::tag::min,
boost::accumulators::tag::max
>>
{
};