I've been using this site for a while and so far never needed to ask a new question (found all answers I've needed until now).
I need to push_back multiple objects into a vector but VS throws an error (This may be due to a corruption of the heap, which indicates a bug in PVSS00DataGate.exe or any of the DLLs it has loaded) that I cannot seem to work out for myself.
Here is what I am trying to do, it works to push_back the first object into the vector but when I try to push_back a second object that is when the error occurs.
class HWObject{}
void DataLogger::WriteNewMessages()
{
unsigned int iBattery = 0;
unsigned int iSignal = 0;
TimeVar tTimeStamp;
// I want to store all HWObjects in a temporary vector (loggerData)
std::vector<HWObject> loggerData;
CharString strElement;
strElement.format( "batteryCondition.value" );
SendOneValuePVSS( (const char *)strElement, iBattery, tTimeStamp );
strElement.format( "signalStrength.value" );
SendOneValuePVSS( (const char *)strElement, iSignal, tTimeStamp );
}
void DataLogger::SendOneValuePVSS(const char *szElementName, double dValue, TimeVar, &tValue)
{
HWObject obj;
obj.setOrgTime(tValue); // Current time
obj.setTimeOfPeriphFlag();
CharString address;
address = strID;
address += ".";
address += szElementName;
obj.setAddress(address);
loggerData.reserve( loggerData.size() + 1 );
loggerData.push_back( obj );
obj.cutData();
}
dataLogger is declared in
class DataLogger
{
public:
std::vector<HWObject> loggerData;
...
}
Here is the class HWObject, I didn't want to overwhelm you with code.
public:
/** Default constructor*/
HWObject();
/** Constructor, which sets the periphAddr and transformationType.
* #param addressString address of the HW object
* #param trans type of transformation
*/
HWObject(const char* addressString, TransformationType trans);
/** Destructor. If the date pointer is not NULL, it is deleted.
*/
virtual ~HWObject();
/** Creates a new HWObject
* This function returns an empty HWObject, no properties are duplicated or copied!
* #classification public use, overload, call base
*/
virtual HWObject * clone() const;
/** Reset all pvss2 relevant parts of the HWObject. when overloading this member
* don't forget to call the basic function!
* #classification public use, overload, call base
*/
virtual void clear();
/** Gets pointer to data
* #return pointer to data
*/
const PVSSchar * getDataPtr() const { return dataPtr; }
/** Gets the data buffer pointer
* #return data buffer pointer
*/
PVSSchar * getData() { return dataPtr; }
/** Cut the data buffer out of the HWObject.
* This function is used to avoid the deletion
* of the data buffer, when a new pointer is set using
* setData() or the HWObject is deleted.
* #return pointer to the data of the HWObject
*/
PVSSchar * cutData();
/** Get the data buffer lenght
* #return length of the data buffer
*/
PVSSushort getDlen() const { return dataLen; }
/** Set ptr to the data buffer, pointer is captured.
* The actual data pointer in the HWObject is deleted,
* if it is not NULL. To avoid the deletion use cutData()
* in order to cut out the pointer.
* #param ptr pointer to new data
*/
void setData(PVSSchar *ptr);
/** Set the data length
* #param len length to be set
*/
void setDlen(const PVSSushort len) { dataLen = len; }
/** Get the periph address
* #return periph address string
*/
const CharString & getAddress() const { return address; }
/** Get the transformation type
* #return type of transformation
*/
TransformationType getType() const { return transType; }
/** Set the transformation type
* #param typ type of transformation for setting
*/
void setType(const TransformationType typ) { transType = typ; }
/** Get the subindex
* #return subindex
*/
PVSSushort getSubindex() const { return subindex; }
/** Set the subindex
* #param sx subindex to be set
*/
void setSubindex( const PVSSushort sx) { subindex = sx; }
/** Get the origin time
* #return origin time
*/
const TimeVar& getOrgTime() const { return originTime; }
/** Get the origin time
* #return oriin time
*/
TimeVar& getOrgTime() { return originTime; }
/** Set the origin time
* #param tm origin time to be set
*/
void setOrgTime(const TimeVar& tm) { originTime = tm; }
/** Get HWObject purpose
* #return objSrcType
*/
ObjectSourceType getObjSrcType() const { return objSrcType; }
/** Set HWObject purpose
* #param tp objSrcType
*/
void setObjSrcType(const ObjectSourceType tp) { objSrcType = tp; }
/** Get number of elements in data buffer
* #return number of elements in data buffer
*/
PVSSushort getNumberOfElements() const { return number_of_elements; }
/** Set number of elements in data buffer
* #param var number of elements in data buffer
*/
void setNumberOfElements(const PVSSushort var) { number_of_elements = var; }
/** Prints the basic HWObject information on stderr.
* in case of overloading don't forget to call the base function!
* #classification public use, overload, call base
*/
virtual void debugPrint() const;
/** Prints th basic HWObject info in one CharString for internal debug DP.
* in case of overloading call base function first, then append specific info
* #classification public use, overload, call base
*/
virtual CharString getInfo() const;
/** Set the periph address
* #param adrStr pointer to address string
*/
virtual void setAddress(const char *adrStr);
/** Set the additional data (flag, orig time, valid user byte,etc)
* #param data aditional flags that be set
* #param subix subindex, use subix 0 for setting values by default
*/
virtual void setAdditionalData(const RecVar &data, PVSSushort subix);
/** Set the 'origin time comes from periph' flag
*/
void setTimeOfPeriphFlag()
{
setSbit(DRV_TIME_OF_PERIPH);
}
/** Check whether time comes from periph
* #return PVSS_TRUE if the time is from perip
*/
PVSSboolean isTimeFromPeriph() const
{
// If isTimeOfPeriph is set, it must be valid
return getSbit(DRV_TIME_OF_PERIPH);
}
/** Set the flag if you want to receive callback if event has answered the value change
*/
void setWantAnswerFlag()
{
setSbit(DRV_WANT_ANSWER);
}
/** Get the status of the 'want answer, flag
*/
PVSSboolean getWantAnswerFlag() const
{
// If isTimeOfPeriph is set, it must be valid
return getSbit(DRV_WANT_ANSWER);
}
/** Set the user bit given by input parameter.
* Status bits defined by the enum DriverBits
* #param bitno bit number
* #return PVSS_TRUE if bit was set
*/
PVSSboolean setSbit(PVSSushort bitno)
{
return (status.set(bitno) && status.set(bitno + (PVSSushort)DRV_VALID_INVALID - (PVSSushort)DRV_INVALID));
}
/** Clear the user bit given by input parameter
* #param bitno bit number
* #return PVSS_TRUE if bit was cleared
*/
PVSSboolean clearSbit(PVSSushort bitno)
{
return (status.clear(bitno) && status.set(bitno + (PVSSushort)DRV_VALID_INVALID - (PVSSushort)DRV_INVALID));
}
PVSSboolean isValidSbit(PVSSushort bitno) const
{
return status.get(bitno + (PVSSushort)DRV_VALID_INVALID - (PVSSushort)DRV_INVALID);
}
/** Check any bit
* #param bitno bit number
* #return status of the bit on bitno position
*/
PVSSboolean getSbit(PVSSushort bitno) const {return status.get(bitno);}
/** Clear all status bits
* return status of clear all
*/
PVSSboolean clearStatus() {return status.clearAll();}
/** Get the status of this object
* #return bit vector status
*/
const BitVec & getStatus() const {return status;}
/** Set status of the bit vector
* #param bv deference to bit vector to be set as status
*/
void setStatus(const BitVec &bv) {status = bv;}
/** Set a user byte in the status.
* #param userByteNo number of user byte range 0..3
* #param val value to set
* #return PVSS_TRUE execution OK
* PVSS_FALSE in case of error
*/
PVSSboolean setUserByte (PVSSushort userByteNo, PVSSuchar val);
/** Reads a user byte from the status.
* #param userByteNo number of user byte range 0..3
* #return the requested user byte
*/
PVSSuchar getUserByte (PVSSushort userByteNo) const;
/** Check validity of user byte.
* #param userByteNo number of user byte range 0..3
* #return PVSS_TRUE user byte is valid
* PVSS_FALSE user byte is not valid
*/
PVSSboolean isValidUserByte(PVSSushort userByteNo) const;
/** Format status bits into a string
* #param str status bits converted to string
*/
void formatStatus (CharString & str) const ;
// ------------------------------------------------------------------
// internal ones
/** Read data from bin file
* #param fp file handle
*/
virtual int inFromBinFile( FILE *fp );
/** Write data to bin file
* #param fp file handle
*/
virtual int outToBinFile( FILE *fp );
/** Set data length
* #param dlen data length
*/
void setDlenLlc (PVSSushort dlen) {dataLenLlc = dlen;}
virtual void updateBufferLlc (HWObject * hwo, int offset1 = 0);
virtual int compareLlc (HWObject * hwo, int offset1 = 0, int offset2 = 0, int len = -1);
/** Get dataLenLlc
* #return dataLenLlc
*/
PVSSushort getDlenLlc () const {return dataLenLlc;}
/** Function to delete the data buffer; overload if special deletion must be done
*/
virtual void deleteData ();
/** Set HW identifier
* #param id hw identifier to be set
*/
void setHwoId(PVSSulong id) {hwoId = id;}
/** Get HW identifier
* #return hw identifier
*/
PVSSulong getHwoId() const {return hwoId;}
protected:
/// the dynamic data buffer
PVSSchar* dataPtr;
/// the data buffer len
PVSSushort dataLen;
/// the pvss2 periph address string
CharString address;
/// the start subix for the data buffer
PVSSushort subindex;
/// the datatype of the data in the buffer (i.e. transformationtype)
TransformationType transType;
/// the time of income, normally set by the constructor
TimeVar originTime;
/// the purpose of this HWObject
ObjectSourceType objSrcType;
/// the number of elements in the data buffer, used for arrays and records
PVSSushort number_of_elements; // fuer array!!!
/// the user bits of the original config
BitVec status;
private:
PVSSushort dataLenLlc;
PVSSulong hwoId;
};
You're not showing the important parts. I'd guess that HWObject has
dynamically allocated memory, and doesn't implement the rule of three
(copy constructor, assignment operator and destructor). But it's only a
guess. (Unless you're using special techniques like reference counting
or smart pointers, copy must do a deep copy, and assignment should
probably use the swap idiom.)
Also, there's no point in reserving size() + 1 just before
push_back.
Related
I have created a threading library and it is used in our company program and the program is a customized software which is in C++ based. As shown in the code below, there are some customized variable types, such as FloatM1D, Ints and etc.
In the threading library, i'm using pthread_create (can't use the newer threading option due the C++ based is in old version) to fire threads that do calculation, then store the results in dictionary for later use.
Multiple threads are fired at one-go (DoEVM routine as shown in the code will be called multiple times at upper level) and wait for each thread completion before retrieval of the result. The thread wait completion (WaitThreadCompletion() as shown in the code) will be called only once.
After the retrieval of the results, I will cleanup all the dictionary.
My problem is, the calculation routine (VSA.calculateEvm() as shown in the code) in the thread is throwing segmentation error intermittently and caused my program hang when it tries to check the thread completion in pthread_join. And I have no access/visible to VSA.calculateEvm() routine because this came from third party library, thus can't debugged deeper.
The error:
An invalid memory reference (segmentation violation) has occurred.
The code from the threading library is provided at below and need some help to check if there is any issue with it that can cause the segmentation error?
Any advise is welcome and thanks in advance.
#define PARALLEL_DEVM_VERSION 2.0
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <EVM.h>
#include <cstdlib>
#include <fstream>
ThreadingModule EVMx;
void *thread_EVM(void *arg);
pthread_mutex_t lock_x = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock_y = PTHREAD_MUTEX_INITIALIZER;
/*THREAD SHARED DATA STRUCTURE*/
struct ThreadData
{
//Warning: Do not use custom variable types in struct, it does not work good with pthread
float if_Freq;
float sample_Rate;
int tnum;
bool enable_Plots;
bool ResequenceIsNeeded;
int if_Bin;
int RAT;
};
typedef struct ThreadData m_ThreadData_Type;
BoolS m_Parallel_EVM;
map<int, FloatM> m_TnumVsDEVM_map;
map<int, FloatM1D> m_Tnum_ReseqArray_map;
map<int, pthread_t> m_TnumVsThreadIds_map;
map<int, FloatM> m_TnumVsResDEVM_map;
map<int, int> m_TnumVsUTPaver_map;
IntS m_tnum;
/*THREAD SHARED DATA - THESE HAVE TO USE WITH MUTEX LOCK */
FloatM1D m_measArrayTmp;
FloatM1D m_refArrayTmp;
UnsignedS m_if_Bin;
UnsignedS m_RAT;
Dot11acChannelType chan_Type;
Dot11PilotTracking pilot_Tracking;
Dot11EqualizerTraining EQ_Train;
Dot11Trigger trig;
StringS wave_ID;
/* RESERVED STRING */
IntS TEST_ID_PREFIX = 1000;
IntS ResequenceTimeDomainToComplex(FloatM1D measArray, FloatM1D complexOutArray, const UnsignedS ifBin, const UnsignedS stride);
IntS Evm (FloatM1D measArray, FloatM1D refArray, const Dot11acChannelType chanType, const Dot11PilotTracking PILOT_TRACK, const FloatS ifFreq, const FloatS sampleRate, const Dot11EqualizerTraining EQ_TRAIN, const Dot11Trigger TRIGGER, OfdmEvmData &evmResults, const BoolS enablePlots = false , const StringS plotTag = "");
BoolS Init(int TestNum, FloatM1D resdevm, IntS resdevmIndex, BoolS enabledataPlots=false, BoolS enableEVMsweep=false, BoolS UTP_AVG=true, IntS NumOfAverage=1);
void WaitThreadCompletion(IntS &totalThreads);
void PostThreadsCleanup();
map<int, FloatM> GetDEVMs();
map<int, FloatM1D> GetResDEVMs();
ThreadingModule::ThreadingModule()
{
//empty constr
}
IntS ThreadingModule::ResequenceTimeDomainToComplex(FloatM1D measArray, FloatM1D &complexOutArray, const UnsignedS ifBin, const UnsignedS stride)
{
/**
* #brief Resequence array wrapper. If in parallel mode, it will do it at EVM thread.
* #param measArray measured array.
* #param complexOutArray array
* #param ifBin argument
* #param stride argument
* #param enableEVMsweep argument
* #return Parallel EVM flag.
*/
IntS rslt;
IntS ret;
/*## PARALLEL MODE ##*/
//Push the array to dictionary, resequence it later
if (!m_Tnum_ReseqArray_map.count(m_tnum)>0){
m_Tnum_ReseqArray_map[m_tnum] = measArray;
m_if_Bin = ifBin;
m_RAT = stride;
} else {
//Fail safe
ERR.ReportError(ERR_GENERIC_WARNING,"Duplicated TNUM found in the dictionary in ResequenceTimeDomainToComplex.",UTL_VOID, NO_SITES, UTL_VOID);
}
return rslt;
}
IntS ThreadingModule::DoEvm(FloatM1D measArray, FloatM1D refArray,const Dot11acChannelType chanType, const Dot11PilotTracking PILOT_TRACK, const FloatS ifFreq, const FloatS sampleRate, const Dot11EqualizerTraining EQ_TRAIN, const Dot11Trigger TRIGGER, OfdmEvmData &evmResults, const BoolS enablePlots, const StringS plotTag)
{
/**
* #brief EVM wrapper.
* #param measArray measured array.
* #param refArray reference array.
* #param chanType channel type.
* #param PILOT_TRACK pilot tracking
* #param ifFreq IF freq.
* #param sampleRate EVM flag sample rate.
* #param Dot11EqualizerTraining equalizer training.
* #param Dot11Trigger trigger.
* #param OfdmEvmData devm results.
* #param enablePlots enable plots
* #param plotTag plot tagging.
* #return Ints not using.
*
*/
IntS rslt, ret;
BoolS m_isResequenceNeeded(false);
FloatM1D m_tmp_meas_Arr;
UnsignedS m_tmpifBin(0);
UnsignedS m_tmpRAT(0);
IntS m_tmp_tnum;
/*## PARALLEL MODE ##*/
/* check if resequence array is needed */
if(m_Tnum_ReseqArray_map.count(m_tnum)>0){
m_isResequenceNeeded=true;
m_tmp_meas_Arr=m_Tnum_ReseqArray_map[m_tnum];
m_tmpifBin= m_if_Bin;
m_tmpRAT=m_RAT;
m_Tnum_ReseqArray_map.erase(m_tnum);
}
/* instantiate the structure */
m_ThreadData_Type *tdata;
tdata =(m_ThreadData_Type *)malloc(sizeof (m_ThreadData_Type));
/* mutex lock to initialize all thread shared variables */
pthread_mutex_lock(&lock_y);
m_measArrayTmp = m_isResequenceNeeded ? m_tmp_meas_Arr : measArray;
m_refArrayTmp = refArray;
chan_Type = chanType;
pilot_Tracking = PILOT_TRACK;
EQ_Train = EQ_TRAIN;
trig = TRIGGER;
wave_ID = plotTag;
pthread_mutex_unlock(&lock_y);
/* thread specific data */
tdata->if_Freq = ifFreq;
tdata->sample_Rate = sampleRate;
tdata->enable_Plots = enablePlots;
tdata->tnum = m_tnum;
tdata->ResequenceIsNeeded=m_isResequenceNeeded;
tdata->if_Bin = m_tmpifBin;
tdata->RAT = m_tmpRAT;
/* create thread */
ret = pthread_create(&m_TnumVsThreadIds_map[m_tnum], NULL, thread_EVM, (void*) tdata);
if (ret!=0) ERR.ReportError(ERR_GENERIC_WARNING , "Error in create EVM thread for TNUM="+ m_tnum.GetText()+".", ret, NO_SITES, UTL_VOID);
return rslt;
}
void* thread_EVM(void* arg)
{
/**
* #brief EVM wrapper.
* #param arg Arguments passed in with structure
*
*/
FloatM1D m_meas_Arr;
FloatM1D m_ref_Arr;
FloatM1D m_cmplx_Arr;
Dot11acChannelType m_chan_Type;
Dot11PilotTracking m_pilot_Tracking;
FloatS m_freq;
FloatS m_sample_Rate;
Dot11EqualizerTraining m_EQ_Train;
Dot11Trigger m_trig;
IntS m_testnum;
BoolS m_enable_Plots;
StringS m_wave_ID;
OfdmEvmData m_evm_Results;
UnsignedS m_Bin;
UnsignedS m_RAT;
BoolS m_isResequencedNeeded(false);
/* initialize all the local variables from arg */
m_ThreadData_Type *tdata;
tdata=(m_ThreadData_Type*)arg;
/* mutex lock to retrieve thread shared data */
pthread_mutex_lock(&lock_y);
m_meas_Arr = m_measArrayTmp;
m_ref_Arr = m_refArrayTmp;
m_pilot_Tracking = pilot_Tracking;
m_EQ_Train = EQ_Train;
m_chan_Type = chan_Type;
m_trig = trig;
m_wave_ID = wave_ID;
pthread_mutex_unlock(&lock_y);
/* initialize thread specific data */
m_freq = tdata->if_Freq;
m_sample_Rate = tdata->sample_Rate;
m_testnum = tdata->tnum;
m_enable_Plots = tdata->enable_Plots;
m_Bin = tdata->if_Bin;
m_RAT = tdata->RAT;
m_isResequencedNeeded = tdata->ResequenceIsNeeded;
/* check if resequence array is needed */
if (m_isResequencedNeeded){
m_cmplx_Arr.Resize(m_ref_Arr.GetSize());
VSA.DOT11.AC.ResequenceTimeDomainToComplex(m_meas_Arr, m_cmplx_Arr, m_Bin, m_RAT);
m_meas_Arr=m_cmplx_Arr;
}
/* perform evm calculation */
VSA.calculateEvm(m_meas_Arr, m_ref_Arr, m_chan_Type, m_pilot_Tracking, m_freq, m_sample_Rate, m_EQ_Train, m_trig, m_evm_Results, m_enable_Plots, m_wave_ID);
pthread_mutex_lock(&lock_x);
m_TnumVsDEVM_map[m_testnum]= m_evm_Results.evm;
pthread_mutex_unlock(&lock_x);
free(tdata);
return NULL;
}
void ThreadingModule::WaitThreadCompletion(IntS &totalThreads)
{
/**
* #brief Check all the created threads are complete.
* #param totalThreads Total number of created threads.
*
*/
int ret;
map<int, pthread_t>::iterator itr;
IntS tnum;
pthread_t threadiD;
/* check each threads if completed */
for (itr = m_TnumVsThreadIds_map.begin(); itr != m_TnumVsThreadIds_map.end(); ++itr) {
tnum = itr->first;
threadiD = itr->second;
ret=pthread_join(threadiD, NULL);
if (ret!=0) ERR.ReportError(ERR_GENERIC_WARNING , "Can't complete the thread for TNUM="+ tnum.GetText()+".", UTL_VOID, NO_SITES, UTL_VOID);
}
totalThreads = m_TnumVsThreadIds_map.size();
}
map<int, FloatM> ThreadingModule::GetDEVMs()
{
return m_TnumVsDEVM_map;
}
map<int, FloatM> ThreadingModule::GetResDEVMs()
{
return m_TnumVsResDEVM_map;
}
void ThreadingModule::PostThreadsCleanup()
{
/**
* #brief Post threads completion cleanup. Make sure to run this only after datalog the results.
* WARNING: Only call this routine when all threads complete executed.
*/
TEST_ID_PREFIX =1000;
m_TnumVsDEVM_map.clear();
m_Tnum_ReseqArray_map.clear();
m_TnumVsThreadIds_map.clear();
m_TnumVsResDEVM_map.clear();
m_TnumVsUTPaver_map.clear();
pthread_mutex_lock(&lock_y);
m_measArrayTmp.Clear();
m_refArrayTmp.Clear();
pthread_mutex_unlock(&lock_y);
}
Doctrine does not generate database schema for ManyToMany relation.
c:\Bitnami\wampstack-5.6.30-0\apache2\htdocs\typejoy.biz>php vendor\doctrine\orm\bin\doctrine orm:schema-tool:create
creates two tables for two entities testChi and testPar, but does not create the #JoinTable "tParChiMTM".
ENtity testChi
<?php
namespace LogBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Table;
use Doctrine\ORM\Mapping\Index;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\JoinTable;
use Doctrine\ORM\Mapping\OneToOne;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\ManyToMany;
use LogBundle\Entity\testPar;
/**
* #Table(name="ttestchi")
* #Entity()
*/
class testChi {
/**
* #var integer
*
* #Column(name="id", type="integer")
* #Id
* #GeneratedValue(strategy="AUTO")
*/
private $id;
/** #Column ( name="name", type="string", length=50, unique=false, nullable=true) */
private $name;
/** #ManyToMany ( targetEntity="testPar", mappedBy="chiMTM") */
private $parMTM;
public function __construct() {
$this->chiMTM = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Get name
*
* #return integer
*/
public function getName()
{
return $this->name;
}
/**
* Set name
* #param integer $name
* #return name
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
//make you have to serialize, deserialize entity here ???
/**
* Get parMTM
*
* #return LogBundle\Entity\ParMTM
*/
public function getParMTM()
{
return $this->parMTM;
}
/**
* Remove parMTM
*
* #param \LogBundle\Entity\testPar $parMTM
*/
public function removeParMTM (\LogBundle\Entity\testPar $parMTM)
{
if ( $this->hasParMTM($parMTM) ) {
$this->parMTM->removeElement($parMTM);
}
}
/**
* Add parMTM
*
* #param \LogBundle\Entity\testPar $parMTM
*
* #return ParMTM
*/
public function addParMTM(\LogBundle\Entity\testPar $parMTM)
{
if ( !$this->hasParMTM($parMTM) ) {
$this->parMTM[] = $parMTM;
}
return $this;
}
/**
* #param \LogBundle\Entity\testPar $parMTM
* #return bool
*/
public function hasParMTM($parMTM)
{
if( $this->getParMTM() ) {
return $this->getParMTM()->contains($parMTM);
}
}
/**
* Return Entity as string
*
* #return string String representation of this class
*/
public function __toString()
{
return strval($this->id);
}
}
Entity testPar
<?php
namespace LogBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Table;
use Doctrine\ORM\Mapping\Index;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\JoinTable;
use Doctrine\ORM\Mapping\OneToOne;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\ManyToMany;
use LogBundle\Entity\testChi;
/**
* #Table(name="ttestpar")
* #Entity()
*/
class testPar {
/**
* #var integer
*
* #Column(name="id", type="integer")
* #Id
* #GeneratedValue(strategy="AUTO")
*/
private $id;
/** #Column ( name="name", type="string", length=50, unique=false, nullable=true) */
private $name;
/** #ManyToMany ( targetEntity="testChi", inversedBy="parMTM") */
/** #JoinTable ( name="tParChiMTM") */
private $chiMTM;
public function __construct() {
$this->chiMTM = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Get name
*
* #return integer
*/
public function getName()
{
return $this->name;
}
/**
* Set name
* #param integer $name
* #return name
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
//make you have to serialize, deserialize entity here ???
/**
* Get chiMTM
*
* #return LogBundle\Entity\ChiMTM
*/
public function getChiMTM()
{
return $this->chiMTM;
}
/**
* Remove chiMTM
*
* #param \LogBundle\Entity\testChi $chiMTM
*/
public function removeChiMTM (\LogBundle\Entity\testChi $chiMTM)
{
if ( $this->hasChiMTM($chiMTM) ) {
$this->chiMTM->removeElement($chiMTM);
}
}
/**
* Add chiMTM
*
* #param \LogBundle\Entity\testChi $chiMTM
*
* #return ChiMTM
*/
public function addChiMTM(\LogBundle\Entity\testChi $chiMTM)
{
if ( !$this->hasChiMTM($chiMTM) ) {
$this->chiMTM[] = $chiMTM;
}
return $this;
}
/**
* #param \LogBundle\Entity\testChi $chiMTM
* #return bool
*/
public function hasChiMTM($chiMTM)
{
if( $this->getChiMTM() ) {
return $this->getChiMTM()->contains($chiMTM);
}
}
/**
* Return Entity as string
*
* #return string String representation of this class
*/
public function __toString()
{
return strval($this->id);
}
}
c:\Bitnami\wampstack-5.6.30-0\apache2\htdocs\typejoy.biz>php vendor\doctrine\orm\bin\doctrine orm:schema-tool:create
creates two tables, but does not create the #JoinTable "tParChiMTM".
The reason was in annotations :
CORRECT
/**
* #ManyToMany ( targetEntity="testPar", mappedBy="chiMTM") */
/**
* #ManyToMany ( targetEntity="testChi", inversedBy="parMTM")
* ( name="tParChiMTM") */
private $chiMTM;
You can not start each line with /**, only the first line shall contain this, the subsequent lines can start only with single *.
WRONG:
/** #ManyToMany ( targetEntity="testChi", inversedBy="parMTM") */
/** #JoinTable ( name="tParChiMTM") */
I'm trying to use the add method to add elements to a LinkedList. This is what the code looks like:
/**
* A singly linked list.
*
* #author
* #version
*/
public class LinkedList<T> {
private ListElement<T> first; // First element in list.
private ListElement<T> last; // Last element in list.
public LinkedList<T> asd;
private int size; // Number of elements in list.
/**
* A list element.
*/
private static class ListElement<T> {
public T data;
public ListElement<T> next;
public ListElement(T data) {
this.data = data;
this.next = null;
}
}
/**
* This TEST METHOD returns true if the following invariants hold:
* <ul>
* <li> size equals the number of list elements, </li>
* <li> if size == 0, first == null and last == null, </li>
* <li> if size > 0, first != null and last != null, </li>
* <li> if size == 1, first == last, </li>
* <li> last.next == null. </li>
* </ul>
*/
public boolean isHealthy() {
return false;
}
/**
* Creates an empty list.
*/
public LinkedList() {
asd = new LinkedList<T>();
}
/**
* Inserts the given element at the beginning of this list.
*/
public void addFirst(T element) {
asd.add(element);
}
/**
* Inserts the given element at the end of this list.
*/
public void addLast(T element) {
}
/**
* Returns the first element of this list.
* Returns <code>null</code> if the list is empty.
*/
public T getFirst() {
// TODO
return null;
}
/**
* Returns the last element of this list.
* Returns <code>null</code> if the list is empty.
*/
public T getLast() {
return null;
}
/**
* Returns the element at the specified position in this list.
* Returns <code>null</code> if <code>index</code> is out of bounds.
*/
public T get(int index) {
return null;
}
/**
* Removes and returns the first element from this list.
* Returns <code>null</code> if the list is empty.
*/
public T removeFirst() {
return null;
}
/**
* Removes all of the elements from this list.
*/
public void clear() {
}
/**
* Returns the number of elements in this list.
*/
public int size() {
return 0;
}
/**
* Returns <code>true</code> if this list contains no elements.
*/
public boolean isEmpty() {
return false;
}
/**
* Returns a string representation of this list. The string
* representation consists of a list of the elements enclosed in
* square brackets ("[]"). Adjacent elements are separated by the
* characters ", " (comma and space). Elements are converted to
* strings by the method toString() inherited from Object.
*/
public String toString() {
return null;
}
}
The problem is that when I try to compile, it generates a "cannot find symbol - method add(T)" error message. I can't see why it wouldn't work, but I'm new to Java so I'd like some help on this.
Yes, LinkedList has add method but the problem is you are not importing java.util.LinkedList. You are implementing your own LinkedList. So either implement a add method for your class, or you can easily use import java.util.LinkedList without implementation.
I have these entities below. There is a 1:m relationship between them.
MetodoPago is PayingMethod, already saved in the database: "credit card", "cash", etc. And Pedido is Order.
Now I want to to associate a paying method to an order, so I have this code:
$pedido = new Pedido();
$repositoryMetodoPago = $this->getDoctrine()->getRepository('ProjectBackendBundle:MetodoPago');
$metodoPago = $repositoryMetodoPago->find(1);
$pedido->setMetodoPago($metodoPago);
$em = $this->getDoctrine()->getManager();
$em->persist($pedido);
$em->flush();
The problem with this code: in the same time the new order is saved, a new MetodoPago is also saved!! Im interested in that since I have already saved all the availablel paying methods.
My try: I have tried this setter:
public function setMetodoPago(\Project\BackendBundle\Entity\MetodoPago $metodoPago = null)
{
$this->metodoPago = $metodoPago->getId();
return $this;
}
but when I try to run the code above, I get
Warning: spl_object_hash() expects parameter 1 to be object, integer given in /vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 1389
Sooo.. what should I do?? These are the entites:
class Pedido
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="MetodoPago", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="metodo_pago_id", referencedColumnName="id")
**/
private $metodoPago;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set metodoPago
*
* #param \Project\BackendBundle\Entity\MetodoPago $metodoPago
* #return Pedido
*/
public function setMetodoPago(\Project\BackendBundle\Entity\MetodoPago $metodoPago = null)
{
var_dump($metodoPago);
$this->metodoPago = $metodoPago;
return $this;
}
/**
* Get metodoPago
*
* #return \Project\BackendBundle\Entity\MetodoPago
*/
public function getMetodoPago()
{
return $this->metodoPago;
}
}
class MetodoPago
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", name="nombre")
*/
protected $nombre;
/**
* #ORM\Column(type="float", name="precio")
*/
protected $precio;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set nombre
*
* #param string $nombre
* #return MetodoPago
*/
public function setNombre($nombre)
{
$this->nombre = $nombre;
return $this;
}
/**
* Get nombre
*
* #return string
*/
public function getNombre()
{
return $this->nombre;
}
/**
* Set precio
*
* #param float $precio
* #return MetodoPago
*/
public function setPrecio($precio)
{
$this->precio = $precio;
return $this;
}
/**
* Get precio
*
* #return float
*/
public function getPrecio()
{
return $this->precio;
}
}
Hi all
I need to declare a variable in Node to keep position of that node so I declare it in node.h
like: std::vector<double> exPosition;(public)
then I defined a simple function for getting this variable like:virtual Vector
GetmyPosition (void) const=0;
then in node.cc I wrote this simple function:
node::GetmyPosition (void) const
{
return exPosition;
}
but when i run it it has this error:
cannot allocate an object of abstract type 'ns3::Node'
note: because the following virtual functions are pure within 'ns3::Node';
here is the complete code for node.h:
#ifndef NODE_H
#define NODE_H
#include <vector>
#include "ns3/object.h"
#include "ns3/callback.h"
#include "ns3/ptr.h"
#include "ns3/net-device.h"
namespace ns3 {
class Application;
class Packet;
class Address;
/**
* \ingroup node
*
* \brief A network Node.
*
* This class holds together:
* - a list of NetDevice objects which represent the network interfaces
* of this node which are connected to other Node instances through
* Channel instances.
* - a list of Application objects which represent the userspace
* traffic generation applications which interact with the Node
* through the Socket API.
* - a node Id: a unique per-node identifier.
* - a system Id: a unique Id used for parallel simulations.
*
* Every Node created is added to the NodeList automatically.
*/
class Node : public Object
{
public:
/// exposition of the node
//std::vector<Ptr<Node> > exPosition;
std::vector<double> exPosition;
/// current position of the node
//std::vector<double> cPosition;
static TypeId GetTypeId (void);
/**
* Must be invoked by subclasses only.
*/
Node();
/**
* \param systemId a unique integer used for parallel simulations.
*
* Must be invoked by subclasses only.
*/
Node(uint32_t systemId);
virtual ~Node();
/**
* \returns the unique id of this node.
*
* This unique id happens to be also the index of the Node into
* the NodeList.
*/
uint32_t GetId (void) const;
/**
* \returns the system id for parallel simulations associated
* to this node.
*/
uint32_t GetSystemId (void) const;
/**
* \param device NetDevice to associate to this node.
* \returns the index of the NetDevice into the Node's list of
* NetDevice.
*
* Associate this device to this node.
*/
uint32_t AddDevice (Ptr<NetDevice> device);
/**
* \param index the index of the requested NetDevice
* \returns the requested NetDevice associated to this Node.
*
* The indexes used by the GetDevice method start at one and
* end at GetNDevices ()
*/
Ptr<NetDevice> GetDevice (uint32_t index) const;
/**
* \returns the number of NetDevice instances associated
* to this Node.
*/
uint32_t GetNDevices (void) const;
/**
* \param application Application to associate to this node.
* \returns the index of the Application within the Node's list
* of Application.
*
* Associated this Application to this Node. This method is called
* automatically from Application::Application so the user
* has little reasons to call this method directly.
*/
uint32_t AddApplication (Ptr<Application> application);
/**
* \param index
* \returns the application associated to this requested index
* within this Node.
*/
Ptr<Application> GetApplication (uint32_t index) const;
/**
* \returns the number of applications associated to this Node.
*/
uint32_t GetNApplications (void) const;
/**
* A protocol handler
*
* \param device a pointer to the net device which received the packet
* \param packet the packet received
* \param protocol the 16 bit protocol number associated with this packet.
* This protocol number is expected to be the same protocol number
* given to the Send method by the user on the sender side.
* \param sender the address of the sender
* \param receiver the address of the receiver; Note: this value is
* only valid for promiscuous mode protocol
* handlers. Note: If the L2 protocol does not use L2
* addresses, the address reported here is the value of
* device->GetAddress().
* \param packetType type of packet received
* (broadcast/multicast/unicast/otherhost); Note:
* this value is only valid for promiscuous mode
* protocol handlers.
*/
typedef Callback<void,Ptr<NetDevice>, Ptr<const Packet>,uint16_t,const Address &,
const Address &, NetDevice::PacketType> ProtocolHandler;
/**
* \param handler the handler to register
* \param protocolType the type of protocol this handler is
* interested in. This protocol type is a so-called
* EtherType, as registered here:
* http://standards.ieee.org/regauth/ethertype/eth.txt
* the value zero is interpreted as matching all
* protocols.
* \param device the device attached to this handler. If the
* value is zero, the handler is attached to all
* devices on this node.
* \param promiscuous whether to register a promiscuous mode handler
*/
void RegisterProtocolHandler (ProtocolHandler handler,
uint16_t protocolType,
Ptr<NetDevice> device,
bool promiscuous=false);
/**
* \param handler the handler to unregister
*
* After this call returns, the input handler will never
* be invoked anymore.
*/
void UnregisterProtocolHandler (ProtocolHandler handler);
/**
* \returns true if checksums are enabled, false otherwise.
*/
static bool ChecksumEnabled (void);
protected:
/**
* The dispose method. Subclasses must override this method
* and must chain up to it by calling Node::DoDispose at the
* end of their own DoDispose method.
*/
virtual void DoDispose (void);
virtual void DoStart (void);
private:
/**
* \param device the device added to this Node.
*
* This method is invoked whenever a user calls Node::AddDevice.
*/
virtual void NotifyDeviceAdded (Ptr<NetDevice> device);
bool NonPromiscReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet>, uint16_t protocol, const Address &from);
bool PromiscReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet>, uint16_t protocol,
const Address &from, const Address &to, NetDevice::PacketType packetType);
bool ReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet>, uint16_t protocol,
const Address &from, const Address &to, NetDevice::PacketType packetType, bool promisc);
void Construct (void);
struct ProtocolHandlerEntry {
ProtocolHandler handler;
Ptr<NetDevice> device;
uint16_t protocol;
bool promiscuous;
};
typedef std::vector<struct Node::ProtocolHandlerEntry> ProtocolHandlerList;
uint32_t m_id; // Node id for this node
uint32_t m_sid; // System id for this node
std::vector<Ptr<NetDevice> > m_devices;
std::vector<Ptr<Application> > m_applications;
ProtocolHandlerList m_handlers;
};
} //namespace ns3
#endif /* NODE_H */
and also the complete code for node.cc
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 Georgia Tech Research Corporation, INRIA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Authors: George F. Riley<riley#ece.gatech.edu>
* Mathieu Lacage <mathieu.lacage#sophia.inria.fr>
*/
#include "node.h"
#include "node-list.h"
#include "net-device.h"
#include "application.h"
#include "ns3/packet.h"
#include "ns3/simulator.h"
#include "ns3/object-vector.h"
#include "ns3/uinteger.h"
#include "ns3/log.h"
#include "ns3/assert.h"
#include "ns3/global-value.h"
#include "ns3/boolean.h"
#include "ns3/simulator.h"
#include "ns3/vector.h"
NS_LOG_COMPONENT_DEFINE ("Node");
namespace ns3{
NS_OBJECT_ENSURE_REGISTERED (Node);
GlobalValue g_checksumEnabled = GlobalValue ("ChecksumEnabled",
"A global switch to enable all checksums for all protocols",
BooleanValue (false),
MakeBooleanChecker ());
//Vector exposition = (0.0, 0.0, 0.0);
/*.AddAttribute ("exPosition", "The previous position of this node.",
TypeId::ATTR_GET,
VectorValue (Vector (0.0, 0.0, 0.0)), // ignored initial value.
MakeVectorAccessor (&Node::m_exposition),
MakeVectorChecker ())
.AddAttribute ("cPosition", "The current position of this node.",
TypeId::ATTR_GET,
VectorValue (Vector (0.0, 0.0, 0.0)), // ignored initial value.
MakeVectorAccessor (&Node::m_cposition),
MakeVectorChecker ())*/
TypeId
Node::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::Node")
.SetParent<Object> ()
.AddConstructor<Node> ()
.AddAttribute ("DeviceList", "The list of devices associated to this Node.",
ObjectVectorValue (),
MakeObjectVectorAccessor (&Node::m_devices),
MakeObjectVectorChecker<NetDevice> ())
.AddAttribute ("ApplicationList", "The list of applications associated to this Node.",
ObjectVectorValue (),
MakeObjectVectorAccessor (&Node::m_applications),
MakeObjectVectorChecker<Application> ())
.AddAttribute ("Id", "The id (unique integer) of this Node.",
TypeId::ATTR_GET, // allow only getting it.
UintegerValue (0),
MakeUintegerAccessor (&Node::m_id),
MakeUintegerChecker<uint32_t> ())
;
return tid;
}
Node::Node()
: m_id(0),
m_sid(0)
{
exPosition.at(1)= 0;
exPosition.at(2)= 0;
exPosition.at(3)= 0;
Construct ();
}
Node::Node(uint32_t sid)
: m_id(0),
m_sid(sid)
{
exPosition.at(1)= 0;
exPosition.at(2)= 0;
exPosition.at(3)= 0;
Construct ();
}
void
Node::Construct (void)
{
m_id = NodeList::Add (this);
//exPosition =(0.0,0.0,0.0);
}
Node::~Node ()
{}
uint32_t
Node::GetId (void) const
{
return m_id;
}
uint32_t
Node::GetSystemId (void) const
{
return m_sid;
}
uint32_t
Node::AddDevice (Ptr<NetDevice> device)
{
uint32_t index = m_devices.size ();
m_devices.push_back (device);
device->SetNode (this);
device->SetIfIndex(index);
device->SetReceiveCallback (MakeCallback (&Node::NonPromiscReceiveFromDevice, this));
Simulator::ScheduleWithContext (GetId (), Seconds (0.0),
&NetDevice::Start, device);
NotifyDeviceAdded (device);
return index;
}
Ptr<NetDevice>
Node::GetDevice (uint32_t index) const
{
NS_ASSERT_MSG (index < m_devices.size (), "Device index " << index <<
" is out of range (only have " << m_devices.size () << " devices).");
return m_devices[index];
}
uint32_t
Node::GetNDevices (void) const
{
return m_devices.size ();
}
uint32_t
Node::AddApplication (Ptr<Application> application)
{
uint32_t index = m_applications.size ();
m_applications.push_back (application);
application->SetNode (this);
Simulator::ScheduleWithContext (GetId (), Seconds (0.0),
&Application::Start, application);
return index;
}
Ptr<Application>
Node::GetApplication (uint32_t index) const
{
NS_ASSERT_MSG (index < m_applications.size (), "Application index " << index <<
" is out of range (only have " << m_applications.size () << " applications).");
return m_applications[index];
}
uint32_t
Node::GetNApplications (void) const
{
return m_applications.size ();
}
void
Node::DoDispose()
{
m_handlers.clear ();
for (std::vector<Ptr<NetDevice> >::iterator i = m_devices.begin ();
i != m_devices.end (); i++)
{
Ptr<NetDevice> device = *i;
device->Dispose ();
*i = 0;
}
m_devices.clear ();
for (std::vector<Ptr<Application> >::iterator i = m_applications.begin ();
i != m_applications.end (); i++)
{
Ptr<Application> application = *i;
application->Dispose ();
*i = 0;
}
m_applications.clear ();
Object::DoDispose ();
}
void
Node::DoStart (void)
{
for (std::vector<Ptr<NetDevice> >::iterator i = m_devices.begin ();
i != m_devices.end (); i++)
{
Ptr<NetDevice> device = *i;
device->Start ();
}
for (std::vector<Ptr<Application> >::iterator i = m_applications.begin ();
i != m_applications.end (); i++)
{
Ptr<Application> application = *i;
application->Start ();
}
Object::DoStart ();
}
void
Node::NotifyDeviceAdded (Ptr<NetDevice> device)
{}
void
Node::RegisterProtocolHandler (ProtocolHandler handler,
uint16_t protocolType,
Ptr<NetDevice> device,
bool promiscuous)
{
struct Node::ProtocolHandlerEntry entry;
entry.handler = handler;
entry.protocol = protocolType;
entry.device = device;
entry.promiscuous = promiscuous;
// On demand enable promiscuous mode in netdevices
if (promiscuous)
{
if (device == 0)
{
for (std::vector<Ptr<NetDevice> >::iterator i = m_devices.begin ();
i != m_devices.end (); i++)
{
Ptr<NetDevice> dev = *i;
dev->SetPromiscReceiveCallback (MakeCallback (&Node::PromiscReceiveFromDevice, this));
}
}
else
{
device->SetPromiscReceiveCallback (MakeCallback (&Node::PromiscReceiveFromDevice, this));
}
}
m_handlers.push_back (entry);
}
void
Node::UnregisterProtocolHandler (ProtocolHandler handler)
{
for (ProtocolHandlerList::iterator i = m_handlers.begin ();
i != m_handlers.end (); i++)
{
if (i->handler.IsEqual (handler))
{
m_handlers.erase (i);
break;
}
}
}
bool
Node::ChecksumEnabled (void)
{
BooleanValue val;
g_checksumEnabled.GetValue (val);
return val.Get ();
}
bool
Node::PromiscReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
const Address &from, const Address &to, NetDevice::PacketType packetType)
{
NS_LOG_FUNCTION(this);
return ReceiveFromDevice (device, packet, protocol, from, to, packetType, true);
}
bool
Node::NonPromiscReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
const Address &from)
{
NS_LOG_FUNCTION(this);
return ReceiveFromDevice (device, packet, protocol, from, from, NetDevice::PacketType (0), false);
}
bool
Node::ReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
const Address &from, const Address &to, NetDevice::PacketType packetType, bool promiscuous)
{
NS_ASSERT_MSG (Simulator::GetContext () == GetId (), "Received packet with erroneous context ; " <<
"make sure the channels in use are correctly updating events context " <<
"when transfering events from one node to another.");
NS_LOG_DEBUG("Node " << GetId () << " ReceiveFromDevice: dev "
<< device->GetIfIndex () << " (type=" << device->GetInstanceTypeId ().GetName ()
<< ") Packet UID " << packet->GetUid ());
bool found = false;
for (ProtocolHandlerList::iterator i = m_handlers.begin ();
i != m_handlers.end (); i++)
{
if (i->device == 0 ||
(i->device != 0 && i->device == device))
{
if (i->protocol == 0 ||
i->protocol == protocol)
{
if (promiscuous == i->promiscuous)
{
i->handler (device, packet, protocol, from, to, packetType);
found = true;
}
}
}
}
return found;
}
}//namespace ns3
I'll be thankful if someone help me about it.
Bests
Bahar
You cannot instantiate an object that has a virtual function declared as =0.
You can have pointers to them, but the pointed elements will actually have a type that inherits from your base class.
GetMyPosition is defined, does it need to be pure virtual? Have you tried removing =0 from function declaration?