How to balance style and efficiecny when accessing two-dimensional array, vector of vectors? - c++

CObject below has vertex arrays and buffers and various other member variables. The question is, how should I access the data in CAgent from CAnotherClass especially with the two-dimensional array (currently vectors) concerning style and also efficiency within and near openGL ES rendering callback function. The vectors of sub-objects are normally reasonable but could get as large as 32,000.
class CObject
{
// vertex arrays, buffers, and data
int val;
public:
int GetValue(){ return val; }
void SetValue( int v ){ val = v; }
};
class CAgent
{
friend class CAnotherClass; // may I, since like an extension?
enum ObjType { a, b, c, };
std::vector< CObject * > m_Objects; // implementation fills these
std::vector< std::vector< CObject * > > m_SubObjects; // each object above has n sub-objects
// for option B below
CObject * GetSubObjectN( int type, int n ) { return m_SubObjects[type][n]; }
std::vector< CObject * > & GetSubObjects( int type ) { return m_SubObjects[type]; }
};
class CAgentSub : public CAgent
{
class CAnotherClass * m_AgentExtension; // really just an extension of this
void Render( double timestamp ); // implementation calls CAnotherClass::Render()
};
class CAnotherClass
{
CAgentSub * m_Agent;
CObject * m_CurrentObject; // for convenience
std::vector< CObject * > * m_CurrentSubObjects;
int m_ObjectType; // or this way
void SetObjectType( int type )
{
m_CurrentObject = m_Agent->m_Objects[type]; // for convenience
m_CurrentSubObjects = &m_Agent->m_SubObjects[type];
m_ObjectType = type; // or this way?
}
void DoSomethingInteresting()
{
int val = -1;
int startVal = 0;
// option A
for ( int n = 0; n < m_CurrentSubObjects->size(); ++n )
{
val = (*m_CurrentSubObjects)[n]->GetValue(); // this is what I'm doing but seems cumbersome
// and not that easy to read
(*m_CurrentSubObjects)[n]->SetValue( startVal );
}
// option B
for ( int n = 0; n < m_Agent->GetSubObjects(m_ObjectType).size(); ++n )
val = m_Agent->GetSubObjectN( m_ObjectType, n )->GetValue();
// option C
for ( int n = 0; n < m_Agent->m_SubObjects[m_ObjectType].size(); ++n )
val = m_Agent->m_SubObjects[m_ObjectType][n]->GetValue();
// option D
for ( std::vector<CObject *>::iterator it = m_Agent->m_SubObjects[m_ObjectType].begin();
it != m_Agent->m_SubObjects[m_ObjectType].end();
++it )
{
(*it)->SetValue( startVal );
}
// setting data at various indexes
int index = 23;
(*m_CurrentSubObjects)[index]->SetValue( startVal );
m_Agent->GetSubObjectN( m_ObjectType, index )->SetValue( startVal );
m_Agent->m_SubObjects[m_ObjectType][index]->SetValue( startVal );
std::vector<CObject *>::iterator nth = m_Agent->m_SubObjects[m_ObjectType].begin() + index;
(*nth)->SetValue( startVal );
}
void Render( double timestamp );
};

Related

How to find/remove an element of vector of struct with specific parameter?

I have a struct of slotAndId struct, which is declared like so
typedef struct {
int slot;
int id;
} slotAndId;
Then I have a vector which holds many objects of type slotAndId...
slotAndId object;
vector<slotAndId> ids;
for (int i = 0; i < 20; i++) {
object.slot = i;
object.id = i + 2000; //random id as example, this will be generated by something else in reality.
ids.push_back(object);
}
If I then wanted to find, for example, if there's a slotAndId object which has slot equal to 20 within the vector, how would I do that in C++98? How would I then be able to delete that specific slotAndId object from the vector?
This is what std::find_if is for.
bool HasSlot20(const slotAndId& item)
{
return item.slot == 20;
}
int main()
{
std::vector<slotAndId> ids = {..};
std::vector<slotAndId>::const_iterator it = std::find_if(
ids.begin(),
ids.end(),
HasSlot20
);
}
We need the extra function because C++98 doesn't have lambdas, but we can make it more flexible by using a functor instead:
struct HasSlot
{
HasSlot(const int id) : m_id(id) {}
bool operator()(const slotAndId& item)
{
return item.slot == m_id;
}
private:
const int m_id;
};
int main()
{
std::vector<slotAndId> ids = {..};
std::vector<slotAndId>::const_iterator it = std::find_if(
ids.begin(),
ids.end(),
HasSlot(20)
);
}
or:
int main()
{
HasSlot finder(20);
std::vector<slotAndId> ids = {..};
std::vector<slotAndId>::const_iterator it = std::find_if(
ids.begin(),
ids.end(),
finder
);
}
Now this logic is re-usable with different parameters.
Alternatively just have a loop!
If your container is very large, you might consider a different (or additional) data structure that can do this in better than linear time.

Map which stores derived objects

I have parent class:
class Data
{
public:
Data ( void ) { }
Virtual int Size ( void )
{
return 100;
}
protected:
map<string, Data*> m;
};
Classes that inherit from class Data:
class Struct : public Data
{
public:
Struct ( void ) { }
Struct & Add ( const string & name, Data x )
{
Data * tmp = new Data ( x );
m[name] = tmp;
return *this;
}
void Print ( void )
{
for ( const auto & tmp : m )
cout << tmp . first << " " << tmp . second -> Size () << endl;
}
};
class IntData : public Data
{
public:
IntData ( void ) { }
int Size ( void )
{
return 4;
}
};
class DoubleData : public Data
{
public:
DoubleData ( void ) { }
int Size ( void )
{
return 8;
}
};
main :
int main ( void )
{
Struct a;
a . Add ( "Integer",IntData () );
a . Print ();
return 0;
}
Current output : Integer 100
Expected output : Integer 4
I want to create a map which would hold various types of objects that are derived from Data class. But when i want to call method Size from stored object in map ( in this case IntData ) which should return 4 It always returns value from parent class Data. How could i fix that please?
There's your problem:
Data * tmp = new Data ( x );
The actual pointer you're putting into the map is an instance of the Data parent class. You're copy-constructing a new instance of the Data parent class from an argument that you're passing, by value, as a parameter.
You need to change this whole function to:
Struct & Add ( const string & name, Data *x)
{
m[name] = x;
return *this;
}
And the caller is now responsible for constructing a new instance of any subclass:
a . Add ( "Integer",new IntData);
Then, this will work as you intended.
Of course, this kind of an approach brings up various issues with memory leaks, etc..., so you're better off using std::shared_ptr. But that would be a different question...
I've rewritten your code for you.
#include <unordered_map>
#include <memory>
#include <iostream>
class Data {
public:
virtual ~Data(){}
virtual int Size() = 0;
};
class Struct : public Data {
std::unordered_map<std::string, std::unique_ptr<Data>> m;
public:
Struct& Add(const std::string& name, std::unique_ptr<Data> x) {
m[name] = std::move(x);
return *this;
}
void Print() {
for(const auto& tmp : m )
std::cout << tmp.first << " " << tmp.second->Size() << "\n";
}
int Size() override {
int sum = 0;
for (const auto& tmp : m)
sum += tmp.second->Size();
return sum;
}
};
class IntData : public Data {
public:
int Size( ) override { return 4; }
};
class DoubleData : public Data {
public:
DoubleData( ) { }
int Size( ) override { return 8; }
};
int main() {
Struct a;
a.Add("Integer", std::make_unique<IntData>() );
a.Print();
}
Your welcome.

implement operator ‘[]’ for class ‘CMatrix’

#include<iostream>
using namespace std;
class Array {
private:
int * data;
int size;
int isValidIndex();
public:
Array ( )
{
data = 0;
size = 0;
}
Array ( int );
Array (const Array &);
Array & operator = ( const Array & );
int & operator [] ( int );
void reSize(int);
~Array();
};
class CMatrix
{
private:
int * * data;
int row;
int col;
//isValidBounds( int , int );
public:
CMatrix ( )
{
data = 0;
row = col = 0;
}
CMatrix ( int r, int c );
CMatrix ( const CMatrix & );
CMatrix & operator = ( const CMatrix & );
//many other functions
};
//Do you feel suitable to implement operator ‘[]’ for class ‘CMatrix’ such that we should be able to manipulate them as follows, If yes then give the definition of operator ‘[]’ for ‘CMatrix’, otherwise given reason (solid/pinpoint) for not implementing this operator.
main()
{
CMatrix m(3,4); //3 by 4 matrix where ist row/col index is 0
m[1][2] = 67;
cout << m[1][2]; //should display 67
}

How can I overload the "new" operator for template classes?

I tried to overload the new operator in the template class below to use malloc instead of new, but I wasn't successful.
template< int SIZE >
class MemPoolT : public MemPool
{
public:
MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
~MemPoolT()
{
for( int i=0; i<blockPtrs.Size(); ++i ) {
delete blockPtrs[i];
}
}
virtual void* Alloc()
{
if ( !root ) {
// Need a new block.
Block* block = new Block();
blockPtrs.Push( block );
for( int i=0; i<COUNT-1; ++i ) {
block->chunk[i].next = &block->chunk[i+1];
}
block->chunk[COUNT-1].next = 0;
root = block->chunk;
}
void* result = root;
root = root->next;
++currentAllocs;
if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
nAllocs++;
return result;
}
private:
enum { COUNT = 1024/SIZE };
union Chunk {
Chunk* next;
char mem[SIZE];
};
struct Block {
Chunk chunk[COUNT];
};
Chunk* root;
int currentAllocs;
int nAllocs;
int maxAllocs;
};
How can I do this?
Is this what you're asking for?
#define malloc new
MemPoolT<N> m = malloc MemPoolT<N>();
Because you should not do that.

Weird error in Turbo C++ IDE - Class template related question

Basically I'm trying to compile a template class which is meant to represent a table for adding up polynomials. As a result of this the table needs to be nullable.
This is the sort of thing I am trying to represent http://www.mathsisfun.com/algebra/polynomials-adding-subtracting.html.
And this is the template which is meant to do it:
template <class T> class TableWithBlanks : public Table<T> {
public:
TableWithBlanks( const int width, const int height ) : w(width), h(height), table_contents( new t_node[width][height]
{
table_contents = new t_node[width][height];
// Go through all the values and blank them.
for( int i = 0; i < w; i++)
{
for( int a = 0; a < h; a++)
{
table_contents[i][a].value_ptr = NULL;
}
}
}
void set_value( const int width, const int height, const T* table_value_ptr)
{
if( width <= w && height <= h )
{
table_contents[w][h] = table_value_ptr;
}
}
T* get_value( const int width, const int height)
{
if( width <= w && height <= h )
{
return table_contents[width][height];
}
}
private:
typedef struct node {
T* value_ptr;
} t_node;
t_node** table_contents;
int w;
int h;
};
And this is the error I am getting:
[C++ Error] TableWithBlanks.h(16):
E2034 Cannot convert
'TableWithBlanks::node
( *)[1]' to
'TableWithBlanks::node
* *'
The PolynomialNode class is a class which is a linked list, where each node in the list represent the terms in a simple polynomial - I don't need to go into details.
In this line, you're trying to dynamically construct a two-dimensional array:
table_contents = new t_node[width][height];
but C++ doesn't work this way. For an example of how to allocate two-dimensional arrays, see this question, for example.