Making an event like subscribing system for C++ * chars - c++

For simple data like ints or constants something like this would work
#include <iostream>
#include <vector>
using namespace std ;
typedef void FuncInt (int) ;
class GraphElementProto {
public:
void add (FuncInt* f)
{
FuncVec.push_back (f) ;
} ;
void call()
{
for (size_t i = 0 ; i < FuncVec.size() ; i++)
FuncVec[i] (i) ;
} ;
private:
vector<FuncInt*> FuncVec ;
} ;
static void f0 (int i) { cout << "f0(" << i << ")" << endl ; }
static void f1 (int i) { cout << "f1(" << i << ")" << endl ; }
int main() {
GraphElementProto a ;
a.add (f0) ;
a.add (f1) ;
a.call() ;
}
So now imagine we work with some data buffer like char.
We have threads that wait for data pointers and on appearance of that pointers want to change data at the same time. So we would need to create copy's of that data and give to each subscriber pointer to his own copy.
So how to do such thing? (sorry C++ nube - code is only thing I can understand)

Consider the similarities between each node of the graph that you describe and create a class for them (class GraphElement below). It should encapsulate its relationship to its child nodes, and it should do something locally with any incoming messages (function localAction). You should then derive classes that represent specific variations - such as the image generator you mention - and change the local action. Each class may take a copy of the original message, or change it as you need.
In my example code here I have create the default graph node - GraphNode - and made it simply print incoming messages before passing them to its child nodes. I have used a string object for the incoming message - a lot nicer than a plain old C char * array [example: you can derive a string from char * when message2 is created in the code below]. I have made those object const references as its cheap, fast, and never changes the original.
I have derived a class called CatNode as an example of the variation you need. Objects of this type contain a history of all messages, and print out that history when a new message arrives. Not very useful - but a good example none the less. This demonstrates how each node may do anything to a copy of the original message - rewrite localAction(). It also passes that history to any child nodes - rewrite incomingMessage with a change to the parameter passed to deliverMessage().
#include <vector>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::vector;
using std::string;
class GraphNode
{
public:
GraphNode( string & name ) : mChildren(), mName(name) {}
GraphNode( const char * const name ) : mChildren(), mName(name==NULL?"":name) {}
virtual void incomingMessage( const string & str ) {
localAction(str); // This node is to do something.
deliverMessage(str); // Child nodes are to do things too.
}
void addChild( GraphNode * child ) {
mChildren.push_back( child );
}
protected:
// Rewrite this function for child classes who are to do different things with messages.
virtual void localAction( const string & str ) {
cout << mName << " : " << str << endl;
}
void deliverMessage( const string & str ) {
vector<GraphNode*>::iterator itr = mChildren.begin();
for( ; itr != mChildren.end(); ++itr )
(*itr)->incomingMessage(str);
}
// Data members
vector<GraphNode*> mChildren;
string mName;
}; // [ GraphNode ]
class CatNode : public GraphNode
{
public:
CatNode( string & name ) : GraphNode(name), mHistory() {}
CatNode( const char * const name ) : GraphNode(name), mHistory() {}
virtual void incomingMessage( const string & str ) {
localAction(str);
deliverMessage(mHistory);
}
protected:
virtual void localAction( const string & str ) {
mHistory += str;
cout << mName << " : " << mHistory << endl;
}
// Data members
string mHistory;
}; // [ CatNode ]
main()
{
// root -> childA
GraphNode root("Root Node");
CatNode childA("Child A");
root.addChild( &childA );
root.incomingMessage("Message1");
cout << endl;
// root -> childA -> childC
// \-> childB
GraphNode childB("Child B");
root.addChild( &childB );
GraphNode childC("Child C");
childA.addChild( &childC );
string message2("Message2");
root.incomingMessage(message2);
} // [ main ]

Related

std string gets corrupted inside class

I am experimenting with building a simple nodegraph library for some projects i have in mind, but i'm hitting what i hope is a really simple roadblock very early on but it has me stumped.
I define objects called NodeDefinitions which are recipes from which nodes can be created in pre-defined configuraitons (number of ports/parameters etc.). NodeDefinition object contains PortDefinition objects that define each of the input/output ports. These PortDefinition objects contain their name (along with some other information in my full code, although removed below for brevity).
My Node class has a Node() constructor that creates a Node given a NodeDefition object. When I use this I create Port objects that each contain a pointer to their corresponding PortDefinition. When I try and print out the name of the port (derived from/stored in the PortDefinition object) it gets corrupted.
Through a little trial and error i have managed to find that if i just pass a std::vector directly to an alternate Node() constructor, then everything appears to work fine.
In the example code below i'm printing out the port names (only one port here), both inside the constructor and then after in the caller.
The definition classes.
class PortDefinition
{
public:
PortDefinition(const std::string & name) : m_name(name)
{}
std::string m_name;
};
class NodeDefinition
{
public:
NodeDefinition(std::vector<PortDefinition> portDefinitions) :
m_portDefinitions(portDefinitions)
{}
std::vector<PortDefinition> m_portDefinitions;
};
The concrete object classes.
class Port
{
public:
Port(PortDefinition * portDefinition) :
m_portDefinition(portDefinition)
{}
const PortDefinition * m_portDefinition;
};
class Node
{
public:
Node(NodeDefinition nodeDefinition) {
std::vector<PortDefinition> portDefs = nodeDefinition.m_portDefinitions;
for (auto & it : portDefs) {
Port newPort = Port( &it );
m_ports.push_back( newPort );
}
print();
}
Node(std::vector<PortDefinition> portDefs) {
for (auto & it : portDefs) {
Port newPort = Port( &it );
m_ports.push_back( newPort );
}
print();
}
void print() const {
std::cout << m_ports.size() << " : ";
for (auto it : m_ports) {
std::cout << "'" << it.m_portDefinition->m_name << "'" << std::endl;
}
}
private:
std::vector<Port> m_ports;
};
The test code.
int main (int argc, const char *argv[])
{
std::vector<PortDefinition> portDefinitions;
portDefinitions.push_back( PortDefinition("Port_A") );
NodeDefinition nodeDefinition = NodeDefinition(portDefinitions);
std::cout << "constuctor N1 : ";
Node N1 = Node(nodeDefinition);
std::cout << "main func N1 : ";
N1.print();
std::cout << std::endl;
std::cout << "constuctor N2 : ";
Node N2 = Node(portDefinitions);
std::cout << "main func N2 : ";
N2.print();
return 1;
}
All of the code can be compiled in a single file together.
When I run this get the following output.
constuctor N1 : 1 : 'Port_A'
main func N1 : 1 : ''
constuctor N2 : 1 : 'Port_A'
main func N2 : 1 : 'Port_A'
As you can see when i print out the port name after using the Node() constructor that uses the NodeDefinition object the name is empty, sometimes I get garbage there instead, which makes me think something is corrupting memory somehow, but i'm a bit lost as to why.
std::vector<PortDefinition> portDefs = nodeDefinition.m_portDefinitions;
for (auto & it : portDefs) {
Port newPort = Port( &it );
m_ports.push_back( newPort );
}
This code is the problem. portDefs is a copy of nodeDefinition.m_portDefinitions, being destroyed when the constructor is finished. But you store a pointer to the these objects with Port(&it).
The print() in the constructor should work fine, but the print() in main now accesses the destroyed copies, which is undefined behaviour.
A possible solution would be to store shared_ptr of your PortDefinition or just store a copy in Port.

c++ - overloading array subscript operator

I'm trying to provide custom exception handling mechanism to a class inherited from mysqlpp::StoreQueryResult in mysql++ library. But what i'm finding really hard to do is to find a way to refer to the actual object within the class, so i'm unable to use the vector operation at() properly in order to retrieve a value at an index.
Here is the header
/* MySQLQueryResult.h */
#ifndef MYSQLQUERYRESULT_H
#define MYSQLQUERYRESULT_H
#include <mysql++.h>
#include <result.h>
namespace MinesScanner {
namespace MoonStone {
class MySQLQueryResult : public mysqlpp::StoreQueryResult {
public:
MySQLQueryResult();
MySQLQueryResult(const MySQLQueryResult &other);
MySQLQueryResult& operator=(const MySQLQueryResult &other);
mysqlpp::Row& operator[](int index);
private:
int _dat;
};
}
}
#endif /* MYSQLQUERYRESULT_H */
Here is the source file
/* MySQLQueryResult.cpp */
#include "MySQLQueryResult.h"
namespace MinesScanner {
namespace MoonStone {
MySQLQueryResult::MySQLQueryResult( )
: StoreQueryResult( )
{
}
MySQLQueryResult::MySQLQueryResult( const StoreQueryResult &ob )
: StoreQueryResult( ob )
{
}
MySQLQueryResult& MySQLQueryResult::operator=( const StoreQueryResult &ob )
{
StoreQueryResult::operator=( ob ) ;
return *this ;
}
mysqlpp::Row& MySQLQueryResult::operator[]( int index )
{
try {
std::cout << " Called " << this->at( index ) << std::endl ;
return this->at( index ) ;
} catch ( std::exception& excpn_ob ) {
std::cerr << " Exception caught : " << excpn_ob.what( ) << std::endl ;
}
}
}
}
A simple usage example will show more clearly what i want to achieve.
#include "MySQLQueryResult.h"
int main() {
StoreQueryResult lisres = getMinesData( ( string ) row.at( 0 ) ) ; // returns StoreQueryResult object storing the result
cout << lisres[0][7] << endl; // outputs "Falkreath Stormcloak Mines"
MySQLQueryResult my_lisres = getMinesData( ( string ) row.at( 0 ) ) ; // returns StoreQueryResult object storing the result
cout << my_lisres[0][7] << endl; // ERROR!
}
So i basically want to add more boundary checking, check for null values , and handle out_of_range exception using the operator[] in class MySQLQueryResult but its not working.
I want to be able to access MySQLQueryResult object using array subscripts . Either i'm getting a garbage value or a Seg fault. Please let me know how to get this right
but its not working
It looks like you also need to overload const version of subscript operator:
const mysqlpp::Row& operator[](int index) const;

C++11 Cereal: load_and_allocate not loading correctly

I am using cereal, a C++11 serialization library. I am uncertain if this is a bug with the library or an issue with how I am using it and I would like some assistance.
Given the following minimal repro which is representative (but not reliant) on my own code I am getting an exception thrown from JSONInputArchive::search as invocated by the line next to my comment in the code sample below (//breaks here.)
I'm currently on commit 436a0a275cda007f137876f37b4fc8783e615352 in this github repro (at the time of writing, the tip of their develop branch.)
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include "cereal/cereal.hpp"
#include "cereal/types/map.hpp"
#include "cereal/types/vector.hpp"
#include "cereal/types/memory.hpp"
#include "cereal/types/string.hpp"
#include "cereal/types/base_class.hpp"
#include "cereal/archives/json.hpp"
#include <cereal/types/polymorphic.hpp>
class BaseClass : public std::enable_shared_from_this<BaseClass> {
public:
virtual ~BaseClass(){}
template <class Archive>
void serialize(Archive & archive){
archive(CEREAL_NVP(name), CEREAL_NVP(baseMember));
}
protected:
BaseClass(const std::string &a_name):
name(a_name){
}
std::string name;
int baseMember; //let this have random junk so we can see if it saves right.
};
class DerivedClass : public BaseClass {
friend cereal::access;
public:
static std::shared_ptr<DerivedClass> make(const std::string &a_name, int a_derivedMember){
return std::shared_ptr<DerivedClass>(new DerivedClass(a_name, a_derivedMember));
}
template <class Archive>
void serialize(Archive & archive){
archive(CEREAL_NVP(derivedMember), cereal::make_nvp("base", cereal::base_class<BaseClass>(this)));
}
private:
DerivedClass(const std::string &a_name, int a_derivedMember):
BaseClass(a_name),
derivedMember(a_derivedMember){
}
template <class Archive>
static DerivedClass * load_and_allocate(Archive &archive){
int derivedMember;
archive(CEREAL_NVP(derivedMember)); //breaks here.
DerivedClass* object = new DerivedClass("", derivedMember);
archive(cereal::make_nvp("base", cereal::base_class<BaseClass>(object)));
return object;
}
int derivedMember;
};
CEREAL_REGISTER_TYPE(DerivedClass);
void saveTest(){
std::stringstream stream;
{
cereal::JSONOutputArchive archive(stream);
auto testSave = DerivedClass::make("TestName", 4);
archive(cereal::make_nvp("test", testSave));
}
std::cout << stream.str() << std::endl;
std::shared_ptr<DerivedClass> loaded;
{
cereal::JSONInputArchive archive(stream);
archive(cereal::make_nvp("test", loaded));
}
std::stringstream stream2;
{
cereal::JSONOutputArchive archive(stream2);
archive(cereal::make_nvp("test", loaded));
}
std::cout << stream2.str() << std::endl;
std::cout << "TA-DA!" << std::endl;
}
int main(){
saveTest();
}
The sample output I get from the above (before the exception) is:
{
"test": {
"id": 1073741824,
"ptr_wrapper": {
"id": 2147483649,
"data": {
"derivedMember": 4,
"base": {
"name": "TestName",
"baseMember": -1163005939
}
}
}
}
}
I've modified the throwing method (in cereal/archive/json.hpp) to print what it is searching for and each of the values it is looking through in an effort to debug the problem. Here is my modified version:
//! Adjust our position such that we are at the node with the given name
/*! #throws Exception if no such named node exists */
inline void search( const char * searchName )//, GenericValue const & parent )
{
size_t index = 0;
std::cout << "_____" << std::endl;
for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index )
if( std::strcmp( searchName, it->name.GetString() ) == 0 )
{
itsIndex = index;
return;
} else{
//I added this part here
std::cout << "!" << searchName << " == " << it->name.GetString() << std::endl;
}
throw Exception("JSON Parsing failed - provided NVP not found");
}
Output for the above method before it excepts:
!derivedMember == id
!derivedMember == data
The output I get from this seems to indicate that search is looking through the members of "test.ptr_wrapper" instead of "test.ptr_wrapper.data".
My question is this: am I doing something wrong? Or is there an issue with cereal?
https://github.com/USCiLab/cereal/issues/42
It seems like this is indeed a bug with Cereal. My temporary work-around is as follows:
For now, to work around the issue I added a line 144 in memory.hpp (as
it appears on line 168 in the case of no load_and_allocate which means
that there is a default constructor.)
ar( *ptr );
I will simply avoid using the load_and_allocate archive
directly and will use my serialization functions. In my
load_and_allocate method I will construct an object with "default"
like information.
When this is fixed I should be able to correctly load in the parameters required to construct the object properly.
*edit: this has been fixed on the develop branch.

Such a thing as C++ design pattern to avoid pointers?

I have a class hierarchy as shown in the example below, where a State contains a list of ZipCodes and a list of Citys, each of which contain pointers to the ZipCodes.
The goal is to be able to update the ZipCodes without needing to update Citys (or to create new instances of City).
The C++ code below meets this requirement, but it uses pointers, which I prefer to avoid because of this and that. How can I re-design this [naive] implementation so that it doesn't rely on pointers? Thanks for any help!
EDIT: Updated code below to use boost::shared_ptr instead of raw pointers. Note that State, City, and ZipCode are just example names, and they turned out to be poor choice names (I could've picked "A", "B", and "C") because the actual code allows the equivalent of City to share ZipCodes.
#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>
using namespace std;
/**
* Zone Improvement Plan (ZIP) code
*/
class ZipCode {
public:
ZipCode() : code_(0), plus4_(0) {}
ZipCode(int code, int plus4 = 0) : code_(code), plus4_(plus4) {}
virtual ~ZipCode() {};
int code() const { return code_; }
int plus4() const { return plus4_; }
void set_code(int code) { code_ = code; }
void set_plus4(int plus4) { plus4_ = plus4; }
private:
int code_;
int plus4_;
};
typedef boost::shared_ptr<ZipCode> ZipPtr;
/**
* City points to one or more zip codes
*/
class City {
public:
const vector<ZipPtr>& zip() const { return zip_; }
void add_zip_ptr(const ZipPtr x) { if (x != NULL) zip_.push_back(x); }
private:
// TODO: this vector should be a hash set
vector<ZipPtr> zip_;
};
/**
* State contains cities, each of which has pointers to
* zip codes within the state.
*/
class State {
public:
const vector<City>& city() const { return city_; }
const vector<ZipPtr>& zip() const { return zip_; }
const ZipPtr zip_of(int code) const {
for (size_t i = 0; i < zip_.size(); i++) {
if (zip_[i]->code() == code) {
return zip_[i];
}
}
return ZipPtr();
}
void add_city(const City& x) { city_.push_back(x); }
void add_zip(int code) { zip_.push_back(ZipPtr(new ZipCode(code))); }
private:
// TODO: these vectors should be hash sets
vector<City> city_;
vector<ZipPtr> zip_;
};
int main() {
State texas;
City dallas, houston;
// create state ZIPs
texas.add_zip(75380);
texas.add_zip(75381);
texas.add_zip(77219);
texas.add_zip(77220);
// point city ZIPs to the ones we just created
dallas.add_zip_ptr(texas.zip_of(75380));
dallas.add_zip_ptr(texas.zip_of(75381));
houston.add_zip_ptr(texas.zip_of(77219));
houston.add_zip_ptr(texas.zip_of(77220));
// print all ZIPs
cout << "ZIPs in Texas: " << endl;
const vector<ZipPtr>& zips = texas.zip();
for (size_t i = 0; i < zips.size(); i++) {
cout << " " << zips[i]->code() << endl;
}
cout << "ZIPs in Dallas, Texas: " << endl;
const vector<ZipPtr> zip_ptrs1 = dallas.zip();
for (size_t i = 0; i < zip_ptrs1.size(); i++) {
cout << " " << zip_ptrs1[i]->code() << endl;
}
cout << "ZIPs in Houston, Texas: " << endl;
const vector<ZipPtr> zip_ptrs2 = houston.zip();
for (size_t i = 0; i < zip_ptrs2.size(); i++) {
cout << " " << zip_ptrs2[i]->code() << endl;
}
// change a state ZIP...
cout << "Changing Houston's ZIP 77220..." << endl;
ZipPtr z = texas.zip_of(77220);
if (z != NULL) z->set_code(88888);
// ...and show the ZIPs of the affected city
cout << "ZIPs in Houston, Texas: " << endl;
const vector<ZipPtr> zip_ptrs3 = houston.zip();
for (size_t i = 0; i < zip_ptrs3.size(); i++) {
cout << " " << zip_ptrs3[i]->code() << endl;
}
return 0;
}
I see the situation as two 1:n relationships
State : City == 1 : n
City : Zipcode
== 1 : n
Based on that, I think that the State containing
vector<ZipCode> zip_;
is not sound.
I might do
class State {
vector< City > cities_in_state_;
};
class City {
vector< Zipcode > zips_in_city_;
};
This does not require pointers.
Unless you want to duplicate your ZipCode objects, you fall into this category of usage (described in your first link):
The Bar instance is actually managed
by some other part of your program,
whereas the Foo class just needs to be
able to access it.
It seems like a legit use.
However, you might want to consider the copy option (to permanently avoid problems if the vector has to reallocate its data) or make State aggregate ZipCodes from its Cities instead of distributing them ZipCodes.
The copy simply implies that you stop using pointers in City. Aggregating the ZipCodes means that instead of giving State a list of ZipCodes, you would give City the list of ZipCode instances, and when calling zip_of, you would iterate through the cities and iterate through their ZipCode collection.

Accessing base class member variable from derived class, instantiated from derived class

I have a problem to access a base class member variable from a derived class thru a interface containing 2 virtual functions. The main purpose is that I need to work with these classes at 2 different programn stages.
First stage is to fill an array with text snippets / sentences thru the ArrayStemmedSnippet class
The second stage, at a later point in the program, is getting items from the sentences array/snippet array defined in the base class thru the SuffixableElement interface class.
I have the strong feeling I am missing some basics here. I think there is a basic design or logic error. Also i have to admit, that I am not a C++ pro, means I am still a C++ beginner, So please bear with me....
Let me show you the code I have:
The class definition:
using namespace std;
// --- class represents a stemmed term of a StemmedSentence object
class StemmedTerm {
private:
string _word;
string _stemmed;
public:
StemmedTerm(string word, string stemmed);
~StemmedTerm();
// --- Implementation of StemmedTerm interface
string getTerm();
string getStemmed();
};
class StemmedSentence;
class SuffixableElement;
// --- a snippet containing stemmed sentences
class ArrayStemmedSnippet {
friend class StemmedSentence;
public:
ArrayStemmedSnippet();
ArrayStemmedSnippet(Array snippetTerms);
~ArrayStemmedSnippet();
SuffixableElement * getSentence(int n);
int size() const;
private:
Array snippet;
Array sentences;
};
// --- a stemmed sentence from ArrayStemmedSnippet
class StemmedSentence : public ArrayStemmedSnippet {
public:
StemmedSentence(ArrayStemmedSnippet *p);
StemmedSentence(const int start, const int end);
virtual ~StemmedSentence();
virtual void * get(int index) const;
virtual int size() const;
private:
int _start;
int _end;
ArrayStemmedSnippet *parent;
};
// --- interface to access a stemmed sentence and its size
class SuffixableElement {
public:
virtual ~SuffixableElement() = 0;
virtual void * get(int index) const = 0;
virtual int size() const = 0;
};
The implementation:
using namespace std;
StemmedSentence::StemmedSentence(const int start, const int end)
: _start(start), _end(end) {
}
StemmedSentence::StemmedSentence(ArrayStemmedSnippet *p)
: parent( p ) {
}
StemmedSentence::~StemmedSentence() {
}
// --- implementation interface SuffixableElement
void * StemmedSentence::get(int index) const {
if (index == (size() - 1)) {
return NULL; // --- End of string (sentence)
}
// get the stemmed term from snippets array in ArrayStemmedSnippet class
// is null, because array is not accessable thru the Suffixable iFace / eg not defined
return snippet[ _start + index ];
}
// --- implementation interface SuffixableElement
int StemmedSentence::size() const {
return _end - _start + 2;
}
// --- add array of snippet terms to sentences. NULL represents end of sentence
ArrayStemmedSnippet::ArrayStemmedSnippet() { }
ArrayStemmedSnippet::ArrayStemmedSnippet(Array snippetTerms)
: snippet( snippetTerms ) {
int index = 0;
for (int i = 0; i < snippetTerms.getLength(); i++) {
if (snippetTerms[ i ] == NULL) {
sentences.append( new StemmedSentence(index, i - 1 ));
index = i + 1;
}
}
}
ArrayStemmedSnippet::~ArrayStemmedSnippet() {
for (int i = 0; i < sentences.getLength(); i++) {
delete sentences[i];
}
}
int ArrayStemmedSnippet::size() const {
return sentences.getLength();
}
// --- returns n-th sentence of this snippet
SuffixableElement * ArrayStemmedSnippet::getSentence(int n) {
StemmedSentence( this ); // --- just a try: try passing base instance to derived class
return (SuffixableElement*)sentences[ n ];
}
The main body:
int main() {
// Sentence 1:
Array stemmed;
StemmedTerm *st1 = new StemmedTerm( "Mouse", "Mouse" );
StemmedTerm *st2 = new StemmedTerm( "ate", "ate" );
StemmedTerm *st3 = new StemmedTerm( "cheese", "cheese" );
stemmed.append( st1 );
stemmed.append( st2 );
stemmed.append( st3 );
stemmed.append( NULL ); // ---- end of snippet sentence
// Sentence 2:
StemmedTerm *st21 = new StemmedTerm( "Cat", "Cat" );
StemmedTerm *st22 = new StemmedTerm( "ate", "ate" );
StemmedTerm *st23 = new StemmedTerm( "cheese", "cheese" );
StemmedTerm *st24 = new StemmedTerm( "too", "too" );
stemmed.append( st21 );
stemmed.append( st22 );
stemmed.append( st23 );
stemmed.append( st24 );
stemmed.append( NULL ); // ---- end of snippet sentence
// ok -- one stemmedsnippet with 2 sentences
ArrayStemmedSnippet ass( stemmed );
// do some sother stuff ... later in the program ....
// --- get elements and size info thru SuffixableElements interface
SuffixableElement *currentElement = (SuffixableElement *)ass.getSentence(1);
cout << "cur. element size=" << currentElement->size() << endl;
StemmedTerm *st = (StemmedTerm*)currentElement->get(2, ass);
string str = st->toString();
cout < "second word is=" << str <&lt endl;
delete st1;
delete st2;
delete st3;
delete st21;
delete st22;
delete st23;
delete st24;
return 1;
}
I skipped some function from above (toString() and other not relevant fct) to keep the
code as short as possible.
So the main problem is when I call
SuffixableElement * currentElement = (SuffixableElement *)ass.getSentence(1);
// --- this works fine!
cout << "cur. element size=" << currentElement->size() << endl;
// --- does not work, because snippet array of base class is uninitalized coming thru the
// --- interface ....
// --- Also passing the instance of the base class ArrayStemmedSnippet with the
// --- getSenctence() Fct does not help.
StemmedTerm * st = (StemmedTerm *)currentElement->get(2); // should return "cheese"
string str = st->toString();
cout << "str=" << str << endl;
What do I have to to that the snippet array is accessable thru the get(int index) call
with the SuffixableElement interface. The size() Fct is no problem, since I instanciated the derived class and access local members _start/_end.
Also StemmedSentence class as a nested class within ArrayStemmedSnippet is not working, unlike Java (I think) C++ wont let me access objects of ArrayStemmedSnippet like that.So I am sure I have some basic misunderstanding.
What I am missing???
Any help is greatly appreciated!!
// --- returns n-th sentence of this snippet
SuffixableElement* ArrayStemmedSnippet::getSentence(int n) {
// ...
return (SuffixableElement*)sentences[ n ];
}
'sentences' is an array of objects of the StemmedSentence class. StemmedSentence is not derived from SuffixableElement, that is it does not provide that interface.
Try the following:
class StemmedSentence : public ArrayStemmedSnippet, public SuffixableElement {
// ...
};
and
SuffixableElement* ArrayStemmedSnippet::getSentence(int n) {
StemmedSentence* sentence = sentences[ n ];
sentence->setParent(this);
return sentence;
}
If SuffixableElement is your interface, then StemmedSentence must derive from it.