C++ - Definition Klassen-template (header - /source-Datei)
Ich will einen Prozessor in voreen (wie diese .cpp | .h) portieren dieses OTB-Anwendung:
http://hg.orfeo-toolbox.org/OTB/file/ca4366bb972e/Applications/Segmentation/otbSegmentation.cxx
Ich programmiert haben, fast alle Parameter in Eigenschaften, etc.. aber
Wenn man sich anschaut, wie Drei hundert sechs und siebzig, werden Sie sehen, eine Klasse Vorlage von FloatVectorImageType::SizeType, ein typedef-Typ.
Ich bin nicht vertraut mit c++ - templates, so war meine erste Frage: wo Stelle ich diese Vorlage, die Implementierung in der .cpp oder .h-file des Prozessors? Nehmen ein kurzer Blick auf c++ - tutorials und andere Prozessor-Beispiele wie die oben, ich herausfinden, ich habe zu erklären, dass die Vorlage im Kopf und definieren Sie es an der .cpp.
Das problem ist, dass der compiler tut mir erlauben, definieren Sie ein template der Klasse ein typedef-Typ innerhalb der .cpp. Die Typdefinition nicht anerkannt..
So, kann mir jemand zeigen in die richtige Richtung hier?
segmentationprocessor.h
#ifndef OTBSEGMENTATIONAPPLICATION_H
#define OTBSEGMENTATIONAPPLICATION_H
#include "otbVectorImage.h"
#include "modules/otb/ports/otbimageport.h"
#include "modules/otb/ports/otbvectorimageport.h"
#include "voreen/core/properties/boolproperty.h"
//..more includes here
namespace voreen {
class OTBSegmentationApplication : public OTBImageFilterProcessor
{
public:
OTBSegmentationApplication();
virtual ~OTBSegmentationApplication();
virtual Processor* create() const;
virtual std::string getCategory() const { return "Applications"; }
virtual std::string getClassName() const { return "Segmentation Application"; }
virtual CodeState getCodeState() const { return CODE_STATE_EXPERIMENTAL;}//STABLE, TESTING, EXPERIMENTAL
virtual std::string getProcessorInfo() const;
/** Images typedefs */
typedef otb::VectorImage<double, 2> VectorImageType;
typedef ImageType LabelImageType;
typedef ImageType MaskImageType;
typedef VectorImageType::SizeType size;
//Segmentation filters typedefs
//Edison mean-shift
typedef otb::MeanShiftVectorImageFilter<VectorImageType,VectorImageType,LabelImageType> EdisonSegmentationFilterType;
EdisonSegmentationFilterType::Pointer edisonFilter;
//Home made mean-shift
typedef otb::MeanShiftSegmentationFilter<VectorImageType, LabelImageType, VectorImageType> MeanShiftSegmentationFilterType;
MeanShiftSegmentationFilterType::Pointer meanshiftFilter;
//Simple connected components
typedef otb::Functor::ConnectedComponentMuParserFunctor<VectorImageType::PixelType> FunctorType;
typedef itk::ConnectedComponentFunctorImageFilter <VectorImageType, LabelImageType, FunctorType, MaskImageType> ConnectedComponentSegmentationFilterType;
ConnectedComponentSegmentationFilterType::Pointer ccFilter;
typedef itk::ScalarConnectedComponentImageFilter<LabelImageType, LabelImageType> LabeledConnectedComponentSegmentationFilterType;
LabeledConnectedComponentSegmentationFilterType::Pointer labeledCCFilter;
//..more typedefs here
protected:
virtual void setDescriptions() {
setDescription("Performs segmentation of an image, and output either a raster or a vector file. In vector mode, large input datasets are supported.");
}
void process();
virtual void initialize() throw (tgt::Exception);
virtual void deinitialize() throw (tgt::Exception);
/** TEMPLATE DECLARATION (?) */
template<class TInputImage, class TSegmentationFilter>
VectorImageType::SizeType GenericApplySegmentation(otb::StreamingImageToOGRLayerSegmentationFilter
<TInputImage, TSegmentationFilter> * streamingVectorizedFilter, TInputImage * inputImage,
const otb::ogr::Layer& layer, const unsigned int outputNb);
virtual void updateFilterSelection();
virtual void updateModeSelection();
private:
OTBVectorImagePort inPort_;
StringOptionProperty filter_; ///< Select segmentation algorithm
OTBVectorImagePort vectorOutPort_;
OTBImagePort vectorMaskInPort_;
OTBImagePort outPort_;
//..more property definitions here
static const std::string loggerCat_; ///< Category used in logging
};
} //namespace
#endif //OTBSEGMENTATIONAPPLICATION_H
segmentationprocessor.cpp
#include "segmentationprocessor.h"
#include "voreen/core/voreenapplication.h"
namespace voreen {
const std::string OTBSegmentationApplication::loggerCat_("voreen.OTBSegmentationApplication");
OTBSegmentationApplication::OTBSegmentationApplication()
:OTBImageFilterProcessor(),
inPort_(Port::INPORT, "IN Multiband Image", 0),
vectorOutPort_(Port::OUTPORT, "OUT Multiband Image", 0),
vectorMaskInPort_(Port::INPORT, "IN Mask Image", 0),
outPort_(Port::OUTPORT, "OUT OTB Image", 0),
filter_("selectFilter", "Segmentation algorithm"),
//.. more properties code here
{
addPort(inPort_);
addPort(vectorOutPort_);
addPort(vectorMaskInPort_);
addPort(outPort_);
addProperty(filter_);
//.. adding the rest of properties here
edisonFilter = EdisonSegmentationFilterType::New();
meanshiftFilter = MeanShiftSegmentationFilterType::New();
ccFilter = ConnectedComponentSegmentationFilterType::New();
//..instantiating more filters needed in implementation here
}
Processor* OTBSegmentationApplication::create() const {
return new OTBSegmentationApplication();
}
OTBSegmentationApplication::~OTBSegmentationApplication() {
}
void OTBSegmentationApplication::initialize() throw (tgt::Exception) {
Processor::initialize();
}
void OTBSegmentationApplication::deinitialize() throw (tgt::Exception) {
Processor::deinitialize();
}
std::string OTBSegmentationApplication::getProcessorInfo() const {
return "Segmentation Application";
}
void OTBSegmentationApplication::updateFilterSelection() {
//code for visual updates on properties here
}
void OTBSegmentationApplication::updateModeSelection() {
//code for visual updates on properties here
}
//TEMPLATE IMPLEMENTATION HERE (?)
template<class TInputImage, class TSegmentationFilter>
OTBSegmentationApplication::VectorImageType::SizeType OTBSegmentationApplication::GenericApplySegmentation(otb::StreamingImageToOGRLayerSegmentationFilter<TInputImage,
TSegmentationFilter> * streamingVectorizedFilter, TInputImage * inputImage, const otb::ogr::Layer& layer, const unsigned int outputNb)
{
typedef TSegmentationFilter SegmentationFilterType;
typedef typename SegmentationFilterType::Pointer SegmentationFilterPointerType;
typedef otb::StreamingImageToOGRLayerSegmentationFilter<TInputImage,SegmentationFilterType> StreamingVectorizedSegmentationOGRType;
//..the rest of template code here
}
void OTBSegmentationApplication::process() {
try
{
//PROCESSOR IMPLEMENTATION GOES HERE
LINFO("Segmentation Application Connected");
}
catch (int e)
{
LERROR("Error in Segmentation Applicationn");
return;
}
}
} //namespace
Fehler: 'VectorImageType' nicht der name eines Typs (fest)
Das war das erste tutorial habe ich aktiviert, danke. Ich konnte kopieren Sie den code in die Frage, aber ich fürchte, sein ein bisschen groß..
Nur die relevant - Teile 😉 oder noch besser ein kurzes, aber vollständiges Beispiel , reproduziert oder zeigt Ihr problem(en)
Auch der Fall von
CurvatureAnisotropicDiffusionImageFilterITK::curvatureAnisotropicDiffusionImageFilterITK
ist sicherlich seltsam. Es ist geschützt, aber definiert .cpp das bedeutet, Dass jede abgeleitete Klasse kann nur die instantiierungen produziert .cpp, die für die Typen float
und double
-- und das sind implizite instantiierungen. Das scheint nicht beabsichtigt.VectorImageType::SizeType OTBSegmentationApplication::GenericApplySegmentation
Versuchen OTBSegmentationApplication::VectorImageType::SizeType OTBSegmentationApplication::GenericApplySegmentation
ich Schreibe eine Antwort für andere Fragen, aber das werde einige Zeit in Anspruch nehmen.InformationsquelleAutor lephleg | 2013-11-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Steckte es in die header-Datei. Das ist die einfachste und stabilste Lösung. Typischerweise werden Sie wollen, um die Definitionen der Funktionen (also Ihre Funktion Körper) in source-Dateien (.cpp), als Quellcode-Dateien kompiliert werden kann, unabhängig. Aber das ist nicht möglich, für Vorlagen(*).
(*) leicht vereinfacht.
Klassen-templates sind nur Blaupausen für die Klassen Funktion Vorlagen sind die Blaupausen für Funktionen. Das ist Funktion Vorlagen sind nicht Funktionen, in anderen Worten "template-Funktion" ist irreführend, es ist keine Funktion, sondern eine Vorlage/Blaupause.
Den Prozess des Aufbaus einer Funktion von einer Funktion Vorlage (oder der Klasse von einer Klasse template) aufgerufen wird Instanziierung. Das Ergebnis ist instantiierte Funktion, oder allgemeiner, eine Funktion Vorlage Spezialisierung.
Template-Spezialisierungen sind keine Vorlagen. Eine Funktion, template-Spezialisierung ist eine gewöhnliche Funktion, die mit dem komischen Namen; eine Klasse template-Spezialisierung ist nur eine Klasse, mit komischen Namen.
Vorlage wird nur instanziiert werden für einige spezifische Gruppen von template-Argumente:
Der zweite Weg ist wesentlich weiter verbreitet. Ein Beispiel:
Diese instanziieren der Klasse Vorlage
my_type
einmal für das Vorlage-argumentint
, und einmal für das Vorlage-argumentdouble
. Dies schafft zwei unabhängige und unabhängigen Typen mit ähnlichen Namen:my_type<int>
undmy_type<double>
Ebenso für Funktionen, außer dass für die Funktionen, die Sie in der Regel nicht explizit die Vorlage Argumente. Stattdessen lassen Sie dem compiler ableiten, die template-Argumente von dem Typen der Funktionsargumente. Beispiel:
Der zweite Anruf wird automatisch ableiten das Vorlage-argument zu sein
int
. Wieder haben wir (implizit instanziiert) zwei Funktionen mit ähnlichen Namen:foo<int>(int)
(der name istfoo<int>
und er hat eine einzige Funktion parameter vom Typint
) undfoo<double>(double)
Warum es schlecht ist, legen Sie die Definitionen der Vorlagen in einer Quellcode-Datei: Siehe Warum können nur Vorlagen umgesetzt werden, die in der header-Datei?
Kurze version: Als Vorlagen sind die Blaupausen, um Sie zu nutzen, hat der compiler instanziiert. Aber es kann nur instanziiert, was es weiß.
Wenn Sie deklarieren eine Funktion Vorlage
foo
in einer header-Dateitempl.h
, definieren Sie es intempl.cpp
und verwenden Sie es inmain.cpp
, dann:In
main.cpp
der compiler nicht wissen, über die definition der Funktion Vorlage. Es kann nur instanziieren der Erklärung vonfoo
, aber nicht die definition.In
templ.cpp
der compiler weiß, dass über die definition, und instanziiert werden kann. Allerdings weiß er nicht, über die Anwendungen außerhalbtempl.cpp
-- es kann daher nicht instanziiert es für alle Sätze der Argumente, die verwendet werden außerhalb.In dem Beispiel In der OP, das funktioniert, aber es scheint ein versehen:
[templ.h]
[templ.cpp]
[main.cpp]
Weil die definition von
foo<char>
noch nicht instanziiert wurde intempl.cpp
, und es kann nicht instanziiert werden, inmain.cpp
ergibt sich ein linker-Fehler.Das ist, warum Sie sollten sich NICHT auf dieses Verhalten. Sie können explizite Instantiierung wenn Sie, aus irgendeinem Grund, tun nicht möchten, definieren Sie die Funktion template in der header-Datei. Zumindest die explizite Instanziierung explizite, und sollten dokumentiert werden, damit keine überraschungen passieren.
Das problem ist der compiler eigentlich beschweren sich über nichts zu tun hat mit templates 😉 Es ist nur ein name-lookup-Problem. Ein Vereinfachtes Beispiel:
Wenn der compiler die Zeile
Bar Foo::do_something()
es siehtBar
, und Sie nicht finden, was, der name bezieht sich auf. Daher der Fehler. Auf der anderen Seite:Nun sagte Sie dem compiler, wo nach dem Namen suchen
Bar
, nämlich innerhalbFoo
.Das Wort "Funktion" hatte Recht, das Beispiel unten der Satz angezeigt, der Typ Abzug aus eine Funktion aufrufen. quimnuss geklärt, hoffe ich. Auch die ersten
>
führt ein Zitat aus dem OP. Es ist auch beabsichtigt.Yep, ich merkte, es war richtig, bekam aber unglücklichen Unternehmen von den schreiben, also habe ich geklärt.
InformationsquelleAutor dyp
Hier ist ein kurzer Beispiel-Vorlagen, die ich schrieb, um Ihnen zu helfen:
im header:
in der Quellcode-Datei:
//explizite template-Instantiierung
InformationsquelleAutor spin_eight