Réponses:
Vous pouvez faire un typedef avant. Mais pour faire
typedef A B;
vous devez d'abord déclarer A
:
class A;
typedef A B;
typedef
nom d'un type de modèle multiniveau complexe utilisant une déclaration directe de cette façon est plutôt complexe et difficile. Sans oublier que cela pourrait nécessiter de plonger dans les détails d'implémentation cachés dans les arguments de modèle par défaut. Et la solution finale est un code long et illisible (en particulier lorsque les types proviennent de divers espaces de noms) très susceptible de changer de type d'origine.
Pour ceux d'entre vous comme moi, qui cherchent à déclarer une structure de style C qui a été définie à l'aide de typedef, dans du code c ++, j'ai trouvé une solution qui va comme suit ...
// 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;
}
Pour "fwd declare a typedef", vous devez déclarer fwd une classe ou une structure, puis vous pouvez typedef déclaré le type. Plusieurs typedefs identiques sont acceptables par le compilateur.
forme longue:
class MyClass;
typedef MyClass myclass_t;
forme courte:
typedef class MyClass myclass_t;
En C ++ (mais pas en C simple), il est parfaitement légal de taper un type deux fois, tant que les deux définitions sont complètement identiques:
// 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);
A
champs de cette manière car A
est vide par définition?
Parce que pour déclarer un type, sa taille doit être connue. Vous pouvez transmettre déclarer un pointeur sur le type, ou typedef un pointeur sur le type.
Si vous le voulez vraiment, vous pouvez utiliser l'idiome pimpl pour réduire les inclusions. Mais si vous souhaitez utiliser un type plutôt qu'un pointeur, le compilateur doit connaître sa taille.
Edit: j_random_hacker ajoute une qualification importante à cette réponse, fondamentalement que la taille doit être connue pour utiliser le type, mais une déclaration directe peut être faite si nous avons seulement besoin de savoir que le type existe , afin de créer des pointeurs ou des références à la type. Étant donné que l'OP n'affichait pas de code, mais se plaignait qu'il ne se compilerait pas, j'ai supposé (probablement correctement) que l'OP essayait d' utiliser le type, pas seulement de s'y référer.
L'utilisation de déclarations avancées au lieu d'un #include
s complet n'est possible que lorsque vous n'avez pas l' intention d'utiliser le type lui-même (dans la portée de ce fichier) mais un pointeur ou une référence à celui-ci.
Pour utiliser le type lui-même, le compilateur doit connaître sa taille - d'où sa déclaration complète doit être vu - d'où un plein #include
est nécessaire.
Cependant, la taille d'un pointeur ou d'une référence est connue du compilateur, quelle que soit la taille de la pointe, donc une déclaration directe est suffisante - elle déclare un nom d'identificateur de type.
Fait intéressant, lorsque vous utilisez un pointeur ou une référence à des types class
ou struct
, le compilateur peut gérer les types incomplets, vous évitant ainsi de déclarer les types de pointe également:
// 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
J'ai eu le même problème, je ne voulais pas jouer avec plusieurs typedefs dans différents fichiers, donc je l'ai résolu avec l'héritage:
était:
class BurstBoss {
public:
typedef std::pair<Ogre::ParticleSystem*, bool> ParticleSystem; // removed this with...
fait:
class ParticleSystem : public std::pair<Ogre::ParticleSystem*, bool>
{
public:
ParticleSystem(Ogre::ParticleSystem* system, bool enabled) : std::pair<Ogre::ParticleSystem*, bool>(system, enabled) {
};
};
A fonctionné comme un charme. Bien sûr, j'ai dû changer toutes les références de
BurstBoss::ParticleSystem
simplement
ParticleSystem
J'ai remplacé le typedef
( using
pour être précis) par l'héritage et l'héritage du constructeur (?).
Original
using CallStack = std::array<StackFrame, MAX_CALLSTACK_DEPTH>;
Remplacé
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;
};
De cette façon, j'ai pu transmettre déclarer CallStack
avec:
class CallStack;
Comme l'a noté Bill Kotsias, la seule façon raisonnable de garder les détails typedef de votre point privé et de les déclarer en avant est avec héritage. Vous pouvez cependant le faire un peu mieux avec C ++ 11. Considère ceci:
// 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;
};
Comme @BillKotsias, j'ai utilisé l'héritage et cela a fonctionné pour moi.
J'ai changé ce gâchis (qui nécessitait tous les en-têtes boost dans ma déclaration * .h)
#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;
dans cette déclaration (* .h)
class VanillaAccumulator;
std::unique_ptr<VanillaAccumulator> acc;
et l'implémentation (* .cpp) a été
#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
>>
{
};