为什么编译器不让我向前声明类型定义?
假设这是不可能的,那么保持我的包含树小的最佳实践是什么?
为什么编译器不让我向前声明类型定义?
假设这是不可能的,那么保持我的包含树小的最佳实践是什么?
当前回答
你可以使用正向类型定义。但是要做
typedef A B;
你必须先向前申报A:
class A;
typedef A B;
其他回答
要“fwd声明一个类型定义”,你需要fwd声明一个类或结构,然后你可以typedef声明类型。编译器可以接受多个相同的类型。
长形式:
class MyClass;
typedef MyClass myclass_t;
简式:
typedef class MyClass myclass_t;
对于那些像我一样,希望在一些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;
}
我用继承和构造函数继承(?)替换了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;
只有当您不打算使用类型本身(在此文件的作用域内),而是使用指向它的指针或引用时,才可以使用前向声明而不是完整的#includes。
要使用类型本身,编译器必须知道它的大小——因此必须看到它的完整声明——因此需要一个完整的#include。
然而,不管被指针的大小如何,编译器都知道指针或引用的大小,因此前向声明就足够了——它声明了一个类型标识符名称。
有趣的是,当使用指向类或结构类型的指针或引用时,编译器可以处理不完整的类型,从而节省了转发声明被指针类型的需要:
// 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
在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);