Antworten:
Sie können typedef weiterleiten. Aber zu tun
typedef A B;
Sie müssen zuerst weiterleiten A
:
class A;
typedef A B;
typedef
Namen beispielsweise einen komplexen mehrstufigen Vorlagentyp verwenden, der eine Vorwärtsdeklaration verwendet, ist dies auf diese Weise ziemlich komplex und schwierig. Ganz zu schweigen davon, dass möglicherweise Implementierungsdetails erforderlich sind, die in Standardvorlagenargumenten versteckt sind. Und die Endlösung ist ein langwieriger und unlesbarer Code (insbesondere wenn Typen aus verschiedenen Namespaces stammen), der sehr anfällig für Änderungen des ursprünglichen Typs ist.
Für diejenigen unter Ihnen wie mich, die eine mit typedef definierte C-artige Struktur in einem C ++ - Code deklarieren möchten, habe ich eine Lösung gefunden, die wie folgt lautet ...
// 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;
}
Um "fwd einen Typedef deklarieren" zu können, müssen Sie eine Klasse oder eine Struktur fwd deklarieren, und dann können Sie den deklarierten Typedef eingeben. Mehrere identische Typedefs werden vom Compiler akzeptiert.
lange Form:
class MyClass;
typedef MyClass myclass_t;
Kurzform:
typedef class MyClass myclass_t;
In C ++ (aber nicht in einfachem C) ist es völlig legal, einen Typ zweimal zu tippen, solange beide Definitionen vollständig identisch sind:
// 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
Felder auf diese Weise, da sie A
per Definition leer sind?
Denn um einen Typ zu deklarieren, muss seine Größe bekannt sein. Sie können einen Zeiger auf den Typ weiterleiten oder einen Zeiger auf den Typ eingeben.
Wenn Sie wirklich wollen, können Sie die Pimpl-Sprache verwenden, um die Includes niedrig zu halten. Wenn Sie jedoch einen Typ anstelle eines Zeigers verwenden möchten, muss der Compiler seine Größe kennen.
Bearbeiten: j_random_hacker fügt dieser Antwort eine wichtige Qualifikation hinzu. Grundsätzlich muss die Größe bekannt sein, um den Typ verwenden zu können. Eine Vorwärtsdeklaration kann jedoch erfolgen, wenn nur bekannt sein muss, dass der Typ vorhanden ist , um Zeiger oder Verweise auf den Typ zu erstellen Art. Da die OP nicht Code zeigen tat, aber beschwerte sich wäre es nicht kompilieren, ging ich davon aus (wahrscheinlich richtig) , dass die OP versuchte , verwenden Sie die Art, nicht nur darauf verweisen.
Die Verwendung von Vorwärtsdeklarationen anstelle eines vollständigen #include
s ist nur möglich, wenn Sie nicht beabsichtigen, den Typ selbst (im Bereich dieser Datei), sondern einen Zeiger oder Verweis darauf zu verwenden.
Um den Typ selbst verwenden zu können, muss der Compiler seine Größe kennen - daher muss seine vollständige Deklaration gesehen werden - daher ist eine vollständige Deklaration #include
erforderlich.
Die Größe eines Zeigers oder einer Referenz ist dem Compiler jedoch unabhängig von der Größe des Pointees bekannt, sodass eine Vorwärtsdeklaration ausreichend ist - sie deklariert einen Typkennungsnamen.
Interessanterweise kann der Compiler bei Verwendung von Zeigern oder Verweisen auf class
oder struct
Typen unvollständige Typen verarbeiten , sodass Sie die Pointee-Typen nicht weiter deklarieren müssen:
// 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
Ich hatte das gleiche Problem, wollte mich nicht mit mehreren Typedefs in verschiedenen Dateien herumschlagen, also habe ich es mit Vererbung gelöst:
war:
class BurstBoss {
public:
typedef std::pair<Ogre::ParticleSystem*, bool> ParticleSystem; // removed this with...
tat:
class ParticleSystem : public std::pair<Ogre::ParticleSystem*, bool>
{
public:
ParticleSystem(Ogre::ParticleSystem* system, bool enabled) : std::pair<Ogre::ParticleSystem*, bool>(system, enabled) {
};
};
Lief wie am Schnürchen. Natürlich musste ich alle Referenzen von ändern
BurstBoss::ParticleSystem
zu einfach
ParticleSystem
Ich habe die typedef
( using
um genau zu sein) durch Vererbung und Konstruktorvererbung (?) Ersetzt .
Original
using CallStack = std::array<StackFrame, MAX_CALLSTACK_DEPTH>;
Ersetzt
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;
};
Auf diese Weise konnte ich deklarieren CallStack
mit:
class CallStack;
Wie Bill Kotsias bemerkte, ist die einzige vernünftige Möglichkeit, die typedef-Details Ihres Punktes privat zu halten und sie weiterzuleiten, die Vererbung. Mit C ++ 11 können Sie es allerdings etwas besser machen. Bedenken Sie:
// 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;
};
Wie @BillKotsias habe ich Vererbung verwendet, und es hat bei mir funktioniert.
Ich habe dieses Durcheinander geändert (für das alle Boost-Header in meiner Deklaration * .h erforderlich waren).
#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;
in diese Erklärung (* .h)
class VanillaAccumulator;
std::unique_ptr<VanillaAccumulator> acc;
und die Implementierung (* .cpp) war
#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
>>
{
};