I have an array as a member of a class. In a subclass, I would like to re-define the array with a different size. I want to do this because I anticipate making many subclasses, each with only the array size it needs, and nothing more.
class Foo
{
Foo() {ivar = 1};
int thisArray[2];
int ivar;
}
class Bar : public Foo
{
Bar() {ivar = 3};
int thisArray[4];
}
int main()
{
Foo myFoo;
Bar myBar;
Foo fooCollection[] = {myFoo,myBar};
cout << "myFoo array size = " << sizeof(myFoo.thisArray)/sizeof(int) << endl;
cout << "myBar array size = " << sizeof(myBar.thisArray)/sizeof(int) << endl;
for (int n=0;n<2;n++)
{
cout << "fooCollection[" << n << "] array size = ";
cout << sizeof(fooCollection[n].thisArray)/sizeof(int) << endl;
}
for (int n=0;n<2;n++)
{
cout << "fooCollection[" << n << "] ivar = ";
cout << fooCollection[n].ivar << endl;
}
}
My results are:
myFoo array size = 2
myBar array size = 4
fooCollection[0] array size = 2
fooCollection[1] array size = 2
fooCollection[0] ivar = 1
fooCollection[1] ivar = 3
I get that, since I declare the array objects as objects of class Foo, that referring to myBar within that scope would reference myBar as though it was a Foo and consequently interpret the size of thisArray as equivalent to 2. I also understand why ivar comes out the way it does.
Is there a way to affect the size of thisArray within the Bar class so its "correct" size can be recognized within an array of Foo objects? I would use a vector, but they are not friendly on the arduino platform. I could also simply make the array within the Foo class with a size of 100, but I am trying to be conscious of memory allocation.
You could template your base class:
template <size_t Size>
class FooBase
{
// etc....
int thisArray[Size];
};
class Foo : public FooBase<2> { ... };
class Bar : public FooBase<4> { ... };
Of course, this is only practical where everything derives from FooBase -- that is, you don't have a class that derives from Bar which needs a different array size.
Also, as has been said in comments, if you need to keep these in an array you need to store pointers.
Foo myFoo;
Bar myBar;
Foo * fooCollection[] = { &myFoo, &myBar };
Oops, there I have assumed that Bar derives from Foo, which it no longer does. If you want a common base that isn't templated, you need to derive the templated class FooBase<Size> from another base FooType and now use an array of FooType. I think that will work.
class FooType {
public:
// etc...
virtual size_t GetSize() const = 0;
};
template <size_t Size>
class FooBase : public FooType
{
public:
// etc...
virtual size_t GetSize() const { return Size; }
protected:
// etc....
int thisArray[Size];
};
And then:
FooType *fooCollection[] = { &myFoo, &myBar };
You can define your array as a pointer and then new it with your constructor and delete it in your destructor. Remember the Rule of Three and you will be fine.
This is unless I've totally misunderstood your intent of this program.
When you do this: cout << sizeof(fooCollection[n].thisArray)/sizeof(int) << endl;, it is impossible to know the size of thisArray because you are not using actual polymorphism. So the compiler assumes all elements in fooCollection are simpy Foo (static binding).
Start by using pointers:
Foo * fooCollection[] = { &myFoo, &myBar };
And declaring a virtual member that will know at runtime the size of the array. (dynamic binding)
virtual int size() {return sizeof(thisArray);}
And then rewriting to:
cout << fooCollection[n]->size()/sizeof(int) << endl;
My opinion would be to not allow the base class to be a concrete class:
Let the base class be a abstract class providing interfaces to the
array (size of array, read and write to the array).
Let the construction and destruction of the array be controlled by the
derived classes.
This way, each derived class can choose the length of its array as appropriate.
Code sketch:
class foo {
public:
virtual size_t array_size() const = 0;
virtual int * array_base() const = 0;
int array_get( size_t index ) const {
array_verify_index( index );
return *( array_base() + index );
}
void array_set( size_t index, int value ) {
array_verify_index( index );
*( array_base() + index ) = value;
}
private:
void array_verify_index( size_t index ) const {
assert( index < array_size() );
}
};
class bar : public foo {
public:
bar() {
array_base = new int[ BarArraySize ];
}
~bar() {
delete [] array_base;
}
virtual size_t array_size() const {
return BarArraySize;
}
virtual int * array_base() const {
return array_base;
}
private:
int * array_base;
};
Well aware that I'm two years late, I would like to add another option - for those who seek an answer to this question without virtual methods or the new operator:
class Foo
{
protected:
// Can only be constructed by Bar, or other derived type.
Foo(int* _array, size_t _size) :
array(_array),
arraySize(_size)
{};
private:
int* array;
size_t arraySize;
};
template<size_t Size>
class Bar : public Foo
{
public:
Bar() : Foo(arrayData, Size) {};
private:
int arrayData[Size];
};
This allows Foo to be a common 'array' interface for several classes, with no virtual methods and with stack allocated arrays. Only real drawback is that we, by necessity, inserted Foo::arraySize, but that's still for a relatively small cost (4/8 bytes on 32/64-bit).
Related
Im learning C++, and I am trying to do a little app. My app takes an informal ticket (without TAX) like this:
2
3 Mi_primera_tablet 7.95
1 El_general_en_su_laberinto Gabriel_García_Márquez 23.50
Where the first line is the number of items
In the second and third line= type of tax + title + price without TAX
The items can be of different types: books(TAX type 3), toys(TAX type 1)
All types inherit from the class article, but depending of the TAX type the price will be different (polymorphism).
I need to store all items (different types) in an array, how can I do it?
You can store pointers in the array.
Exapmle (c++11):
#include <iostream>
#include <vector>
#include <memory>
struct A {
int value;
};
struct B {
double item;
};
class Element {
public:
explicit Element(A a);
explicit Element(B b);
const A * AsA() const;
const B * AsB() const;
private:
class AbstractElement {
public:
virtual ~AbstractElement() {
}
protected:
AbstractElement() {
}
};
template <typename T>
struct ConcreteElement : public AbstractElement {
T body;
explicit ConcreteElement(T input_body)
: body(std::move(input_body)) {
}
};
std::unique_ptr<AbstractElement> element_;
};
Element::Element(A a)
: element_(new ConcreteElement<A>(a)) {
}
Element::Element(B b)
: element_(new ConcreteElement<B>(b)) {
}
const A * Element::AsA() const {
const auto concrete_element =
dynamic_cast<ConcreteElement<A> *>(element_.get());
return concrete_element ? &(concrete_element->body) : nullptr;
}
const B * Element::AsB() const {
const auto concrete_element =
dynamic_cast<ConcreteElement<B> *>(element_.get());
return concrete_element ? &(concrete_element->body) : nullptr;
}
int main() {
std::vector<Element> values;
values.push_back(Element(A{1}));
values.push_back(Element(B{1.5}));
values.push_back(Element(A{-5}));
values.push_back(Element(B{0}));
for (const auto & element : values) {
const auto p_a = element.AsA();
if (p_a) {
std::cout << "A: " << p_a->value << std::endl;
} else {
const auto p_b = element.AsB();
std::cout << "B: " << p_b->item << std::endl;
}
}
return 0;
}
output:
A: 1
B: 1.5
A: -5
B: 0
Maybe you can try boost::variant library, it act as a wrapper around anything. then you can store many boost::variant wrapper in an array
if I understood your question correctly, you need to know how to define an array of your base class with it's derived classes. If this is the case, you can do it by defining an array in the base class, which in your case would look something like this:
article ArrayName [n];
Books Books = new Books();
//do some thing with the books object
ArrayName[0] = Books;
All types inherit from the class article, but depending of the TAX
type the price will be different (polymorphism).
type or TAX type could be stored as a member in Class article.
No polymorphism is needed here.
The items can be of different types: books(TAX type 3), toys(TAX type
1)
Or you could store only the type (books, toys), and do a lookup in a table type | TAX-type, if the TAX types will always be the same for the full range of each type.
But if you really have or need a derived class for each type (for example to store different properties), you could call a virtual function in the derived classes CalcTax() for example.
An array with (baseclass*) pointers to the items could be created, and you can loop through that array, and call CalcTax() on each item, which will call the correct virtual function.
For example:
#include <iostream>
class Base
{
public:
virtual CalcTax() = 0;
};
class Type_1 : public Base
{
public:
virtual CalcTax() {std::cout << "Type_1\n";}
};
class Type_2
{
public:
virtual CalcTax() {std::cout << "Type_2\n";}
};
int main()
{
Base *arrItems[2]; // or better use std::vector<> etc.
Type_1 t1; // just a quick demo of polymorphism
Type_2 t2;
arrItems[0] = (Base*)&t1;
arrItems[1] = (Base*)&t2;
for (int i = 0; i < 2; ++i) {
arrItems[i]->CalcTax();
}
return 0;
}
I have my main.cpp like this:
#include <iostream>
#include "curve1.h"
#include "curve2.h"
using namespace std;
int main()
{
Curve1 curve1Obj;
Curve2 curve2Obj;
curve1Obj.enterScores();
curve1Obj.calcAverage();
curve1Obj.output();
curve1Obj.curve();
curve1Obj.output(curve1Obj.new_getAverage1(), curve1Obj.new_getScore1());
curve2Obj.curve();
return 0;
}
Base class Score has two derived classes Curve1 and Curve2. There are two curve() functions, one is in Curve1 and other in Curve2 classes. getSize() returns the value of iSize.
My base class header score.h looks like this:
#ifndef SCORE_H
#define SCORE_H
class Score
{
private:
int *ipScore;
float fAverage;
int iSize;
public:
Score(
void enterScores();
void calcAverage();
void output();
void output(float, int*);
void setSize();
int getSize();
void setScore();
int *getScore();
float getAverage();
};
#endif
You can see that I have used curve1Obj to enter scores, calculate average and output. So if I call getSize() function with cuve1Obj, it gives the right size that I took from user in enterScores() function. Also the result is same if I call getSize() in score.cpp definition file in any of the functions (obviously).
.....
The problem is when I call curve() function of Curve2 class in main (line 23) with the object curve2Obj, it creates a new set of ipScore, fAverage and iSize (i think?) with garbage values. So when I call getSize() in curve() definition in curve2.cpp, it outputs the garbage.
.....
How can I cause it to return the old values that are set in curve1.cpp?
Here is my curve2.cpp
#include <iostream>
#include "curve2.h"
using namespace std;
void Curve2::curve()
{
cout << "getSize() returns: " << getSize() << endl; // out comes the garbage
}
Can I use a function to simply put values from old to new variables? If yes then how?
Well, basically your problem can't be easily solved the way it is.
Like you said:
1 - Don't use constructors of any type.
2 - Don't use vectors.
3 - Using dynamic new and delete etc. etc.
Use the constructors or stick with what G. Samaras and Richard Hodges said. You can only solve this that way.
There is limited information available here but I would say that your Score constructor has not initialised ipScore or iSize.
If you are hell-bent on using a pointer to a dynamically allocated array of ints for your score then at least null out the pointer in the constructor and test for null in the average function (i.e. no scores yet).
Better yet... use a std::vector of int for your scores.
Why are people still using new and delete? What the hell are they teaching in schools?
What I think you want is this:
#include <vector>
class Score {
public:
Score()
: _scores()
, _average(0)
{ }
void calcAverage() {
double total = 0;
if(auto s = _scores.size() > 0) {
for (const auto& v : _scores)
total += v;
total /= s;
}
_average = total;
}
virtual void curve() = 0;
protected:
// one of the few correct uses of 'protected' - giving limited access to data as interface to derived classes
const std::vector<double>& scores() const {
return _scores;
}
// or
std::vector<double> copyScores() const {
return _scores;
}
private:
// use doubles since you'll be doing floating point arithmetic
std::vector<double> _scores;
double _average;
};
class Curve1 : public Score {
public:
virtual void curve() override {
// custom curve function here
// written in terms of scores() or copyScores() if you want to make changes to the array
}
};
class Curve2 : public Score {
public:
virtual void curve() override {
// custom curve function here
// written in terms of scores();
}
};
You need to understand inheritance. Curve1 inherits from Score. Curve2 inherits from Score.
Now see this example:
#include <iostream>
class Base {
int x;
};
class A : public Base {
int a;
public:
void set_a(int arg) {
a = arg;
}
int get_a() {
return a;
}
};
class B : public Base {
int b;
public:
void set_b(int arg) {
b = arg;
}
int get_b() {
return b;
}
};
int main() {
A a_object;
a_object.set_a(4);
B b_object;
b_object.set_b(a_object.get_a());
std::cout << "a of a_object = " << a_object.get_a() << "\n";
std::cout << "b of b_object = " << b_object.get_b() << "\n";
return 0;
}
class A, has as members x and a. Class B has as members x and b.
When I create an instance of class A, I will two data members created internally, x and a.
When I create an instance of class A, I will two data members created internally, x and b.
But, the first x and the second are DIFFERENT. They are a different cell in the memory!
something like this:
class Score {
public:
Score()
: _scores(0)
, _size(0)
, _average(0)
{ }
// copy constructor
Score(const Score& rhs)
: _scores( new double[rhs._size] )
, _size(rhs._size)
, _average(rhs._average)
{
if (_size) {
for(int i = 0 ; i < _size ; ++i) {
_scores[i] = rhs._scores[i];
}
}
}
// ... and if copy constructor then always a copy operator
Score& operator=(const Score& rhs) {
// assignment in terms of copy constructor - don't repeat yourself
Score tmp(rhs);
swap(tmp);
return *this;
}
// pre c++11 we make our own swap.
// post c++11 we would make non-throwing move constructor and move-assignment operator
void swap(Score& rhs) {
// std::swap is guaranteed not to throw
std::swap(_scores, rhs._scores);
std::swap(_size, rhs._size);
std::swap(_average, rhs._average);
}
~Score()
{
delete[] _scores;
}
void calcAverage() {
double total = 0;
if(_size > 0) {
for (int i = 0 ; i < _size ; ++i)
total += _scores[i];
total /= _size;
}
_average = total;
}
virtual void curve() {};
private:
// use doubles since you'll be doing floating point arithmetic
double * _scores;
int _size;
double _average;
};
// rmember to override the copy operators and assignment operators of derived classes
// remember to call the base class's operator
Let's say you have this:
class foo {
public:
virtual int myFunc() = 0;
///...
virtual bool who() = 0; // don't want to implement this
};
class bar : public foo {
public:
int myFunc() {return 3;}
//...
bool who() {return true;} // don't want to implement this
};
class clam : public foo {
public:
int myFunc() {return 4;}
//...
bool who() {return false;} // don't want to implement this
};
int main() {
std::vector<foo*> vec (2, NULL);
vec[0] = new bar();
vec[1] = new clam();
// copy vec and allocate new ptrs as copies of the data pointed to by vec[i]
std::vector<foo*> vec2 (vec.size(), NULL);
for ( int i=0; i<vec.size(); ++i ) {
// obviously not valid expression, but it would be nice if it were this easy
//vec2[i] = new foo(*vec[i]);
// the hard way of copying... is there easier way?
if (vec[i]->who()) {
vec2[i] = new bar ( * static_cast<bar* >(vec[i]) ) ;
} else {
vec2[i] = new clam( * static_cast<clam*>(vec[i]) );
}
}
return 0;
}
What I want is some simple way of having the compiler look up in its bookkeeping and allocating/copying vec2[i] according to the stored type of *vec[i]. The workaround is to just make a virtual function which basically returns a value specifying what type *vec[i] is, then doing a conditional allocation based on that.
A common approach goes like this:
class foo {
public:
virtual foo* clone() = 0;
};
class bar : public foo {
public:
virtual bar* clone() { return new bar(*this); }
};
class clam : public foo {
public:
virtual clam* clone() { return new clam(*this); }
};
One way you can do it is by using a dynamic cast to determine type of an object such as done here (Finding the type of an object in C++). but the easiest way would probably be to use typeid.
(assuming you want to maintain your way of using type as a determiner, otherwise I would recommend Joachim's or Igor's as better alternatives :) )
you can use the dynamic_cast to downcast and test the type,
bar* pbar = dynamic_cast<bar*>(vec[i])
if (pbar) {
vec2[i] = new bar ( * static_cast<bar* >(vec[i]) ) ;
} else {
vec2[i] = new clam( * static_cast<clam*>(vec[i]) );
}
see for more info in dynamic_cast
http://www.cplusplus.com/doc/tutorial/typecasting/
In C++, the T q = dynamic_cast<T>(p); construction performs a runtime cast of a pointer p to some other pointer type T that must appear in the inheritance hierarchy of the dynamic type of *p in order to succeed. That is all fine and well.
However, it is also possible to perform dynamic_cast<void*>(p), which will simply return a pointer to the "most derived object" (see 5.2.7::7 in C++11). I understand that this feature probably comes out for free in the implementation of the dynamic cast, but is it useful in practice? After all, its return type is at best void*, so what good is this?
The dynamic_cast<void*>() can indeed be used to check for identity, even if dealing with multiple inheritance.
Try this code:
#include <iostream>
class B {
public:
virtual ~B() {}
};
class D1 : public B {
};
class D2 : public B {
};
class DD : public D1, public D2 {
};
namespace {
bool eq(B* b1, B* b2) {
return b1 == b2;
}
bool eqdc(B* b1, B *b2) {
return dynamic_cast<void*>(b1) == dynamic_cast<void*>(b2);
}
};
int
main() {
DD *dd = new DD();
D1 *d1 = dynamic_cast<D1*>(dd);
D2 *d2 = dynamic_cast<D2*>(dd);
std::cout << "eq: " << eq(d1, d2) << ", eqdc: " << eqdc(d1, d2) << "\n";
return 0;
}
Output:
eq: 0, eqdc: 1
Bear in mind that C++ lets you do things the old C way.
Suppose I have some API in which I'm forced to smuggle an object pointer through the type void*, but where the callback it's eventually passed to will know its dynamic type:
struct BaseClass {
typedef void(*callback_type)(void*);
virtual callback_type get_callback(void) = 0;
virtual ~BaseClass() {}
};
struct ActualType: BaseClass {
callback_type get_callback(void) { return my_callback; }
static void my_callback(void *p) {
ActualType *self = static_cast<ActualType*>(p);
...
}
};
void register_callback(BaseClass *p) {
// service.register_listener(p->get_callback(), p); // WRONG!
service.register_listener(p->get_callback(), dynamic_cast<void*>(p));
}
The WRONG! code is wrong because it fails in the presence of multiple inheritance (and isn't guaranteed to work in the absence, either).
Of course, the API isn't very C++-style, and even the "right" code can go wrong if I inherit from ActualType. So I wouldn't claim that this is a brilliant use of dynamic_cast<void*>, but it's a use.
Casting pointers to void* has its importance since way back in C days.
Most suitable place is inside the memory manager of Operating System. It has to store all the pointer and the object of what you create. By storing it in void* they generalize it to store any object on to the memory manager data structure which could be heap/B+Tree or simple arraylist.
For simplicity take example of creating a list of generic items(List contains items of completely different classes). That would be possible only using void*.
standard says that dynamic_cast should return null for illegal type casting and standard also guarantees that any pointer should be able to type cast it to void* and back from it with only exception of function pointers.
Normal application level practical usage is very less for void* typecasting but it is used extensively in low level/embedded systems.
Normally you would want to use reinterpret_cast for low level stuff, like in 8086 it is used to offset pointer of same base to get the address but not restricted to this.
Edit:
Standard says that you can convert any pointer to void* even with dynamic_cast<> but it no where states that you can not convert the void* back to the object.
For most usage, its a one way street but there are some unavoidable usage.
It just says that dynamic_cast<> needs type information for converting it back to the requested type.
There are many API's that require you to pass void* to some object eg. java/Jni Code passes the object as void*.
Without type info you cannot do the casting.If you are confident enough that type requested is correct you can ask compiler to do the dynmaic_cast<> with a trick.
Look at this code:
class Base_Class {public : virtual void dummy() { cout<<"Base\n";} };
class Derived_Class: public Base_Class { int a; public: void dummy() { cout<<"Derived\n";} };
class MostDerivedObject : public Derived_Class {int b; public: void dummy() { cout<<"Most\n";} };
class AnotherMostDerivedObject : public Derived_Class {int c; public: void dummy() { cout<<"AnotherMost\n";} };
int main () {
try {
Base_Class * ptr_a = new Derived_Class;
Base_Class * ptr_b = new MostDerivedObject;
Derived_Class * ptr_c,*ptr_d;
ptr_c = dynamic_cast< Derived_Class *>(ptr_a);
ptr_d = dynamic_cast< Derived_Class *>(ptr_b);
void* testDerived = dynamic_cast<void*>(ptr_c);
void* testMost = dynamic_cast<void*>(ptr_d);
Base_Class* tptrDerived = dynamic_cast<Derived_Class*>(static_cast<Base_Class*>(testDerived));
tptrDerived->dummy();
Base_Class* tptrMost = dynamic_cast<Derived_Class*>(static_cast<Base_Class*>(testMost));
tptrMost->dummy();
//tptrMost = dynamic_cast<AnotherMostDerivedObject*>(static_cast<Base_Class*>(testMost));
//tptrMost->dummy(); //fails
} catch (exception& my_ex) {cout << "Exception: " << my_ex.what();}
system("pause");
return 0;
}
Please correct me if this is not correct in any way.
it is usefull when we put the storage back to memory pool but we only keep a pointer to the base class. This case we should figure out the original address.
Expanding on #BruceAdi's answer and inspired by this discussion, here's a polymorphic situation which may require pointer adjustment. Suppose we have this factory-type setup:
struct Base { virtual ~Base() = default; /* ... */ };
struct Derived : Base { /* ... */ };
template <typename ...Args>
Base * Factory(Args &&... args)
{
return ::new Derived(std::forward<Args>(args)...);
}
template <typename ...Args>
Base * InplaceFactory(void * location, Args &&... args)
{
return ::new (location) Derived(std::forward<Args>(args)...);
}
Now I could say:
Base * p = Factory();
But how would I clean this up manually? I need the actual memory address to call ::operator delete:
void * addr = dynamic_cast<void*>(p);
p->~Base(); // OK thanks to virtual destructor
// ::operator delete(p); // Error, wrong address!
::operator delete(addr); // OK
Or I could re-use the memory:
void * addr = dynamic_cast<void*>(p);
p->~Base();
p = InplaceFactory(addr, "some", "arguments");
delete p; // OK now
Don't do that at home
struct Base {
virtual ~Base ();
};
struct D : Base {};
Base *create () {
D *p = new D;
return p;
}
void *destroy1 (Base *b) {
void *p = dynamic_cast<void*> (b);
b->~Base ();
return p;
}
void destroy2 (void *p) {
operator delete (p);
}
int i = (destroy2 (destroy1 (create ())), i);
Warning: This will not work if D is defined as:
struct D : Base {
void* operator new (size_t);
void operator delete (void*);
};
and there is no way to make it work.
This might be one way to provide an Opaque Pointer through an ABI. Opaque Pointers -- and, more generally, Opaque Data Types -- are used to pass objects and other resources around between library code and client code in such a way that the client code can be isolated from the implementation details of the library. There are other ways to accomplish this, to be sure, and maybe some of them would be better for a particular use case.
Windows makes a lot of use of Opaque Pointers in its API. HANDLE is, I believe, generally an opaque pointer to the actual resource you have a HANDLE to, for example. HANDLEs can be Kernel Objects like files, GDI objects, and all sorts of User Objects of various kinds -- all of which must be vastly different in implementation, but all are returned as a HANDLE to the user.
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
/*** LIBRARY.H ***/
namespace lib
{
typedef void* MYHANDLE;
void ShowObject(MYHANDLE h);
MYHANDLE CreateObject();
void DestroyObject(MYHANDLE);
};
/*** CLIENT CODE ***/
int main()
{
for( int i = 0; i < 25; ++i )
{
cout << "[" << setw(2) << i << "] :";
lib::MYHANDLE h = lib::CreateObject();
lib::ShowObject(h);
lib::DestroyObject(h);
cout << "\n";
}
}
/*** LIBRARY.CPP ***/
namespace impl
{
class Base { public: virtual ~Base() { cout << "[~Base]"; } };
class Foo : public Base { public: virtual ~Foo() { cout << "[~Foo]"; } };
class Bar : public Base { public: virtual ~Bar() { cout << "[~Bar]"; } };
};
lib::MYHANDLE lib::CreateObject()
{
static bool init = false;
if( !init )
{
srand((unsigned)time(0));
init = true;
}
if( rand() % 2 )
return static_cast<impl::Base*>(new impl::Foo);
else
return static_cast<impl::Base*>(new impl::Bar);
}
void lib::DestroyObject(lib::MYHANDLE h)
{
delete static_cast<impl::Base*>(h);
}
void lib::ShowObject(lib::MYHANDLE h)
{
impl::Foo* foo = dynamic_cast<impl::Foo*>(static_cast<impl::Base*>(h));
impl::Bar* bar = dynamic_cast<impl::Bar*>(static_cast<impl::Base*>(h));
if( foo )
cout << "FOO";
if( bar )
cout << "BAR";
}
I have a raw buffer which contains number of different structs(which I couldn't modify) which I planned to wrapped inside a class like below so that I could invoke the virtual Process based on the concrete type.
class Base{
public:
virtual void Process();
};
class DerivedA : public Base {
private:
char* structBuf;
public:
virtual void Process();
}
class DerivedB : public Base {
private:
char* structBuf;
public:
virtual void Process();
}
int main()
{
for(int i = 0 ; i < 10; i++)
{
Base* a = FactoryObject();
a->Process();
}
}
My question is some of the objects depent on each other. For example, let say derivedA data would be processed first and derivedB needs the data from derivedA.
How or where could I store the derivedA object in main() so that I could utilize it in derivedB?
How could I know which objects from factory is derivedA so that I could store it?
Add a constructor to DerivedB that takes a DerivedA parameter. Construct your DerivedB instance only after you processed your DerivedA instance, passing to DerivedB the DerivedA instance.
I think I'm understanding your question.
In main you would have your object that holds the data you want passed around. Have a derivedA public data object (or you can make it private and set it with a set function) and make derivedA.data = main's data. Then when derivedA does its stuff, the object in main will still point to it. Then you repeat the process by handing the data to derivedB with derivedB.data = main's data.
If you make char* structBuf; protected instead of private then all derived classes can access it. As it stands I'm not sure how you'll implement the process function in your derived classes.
It sounds like you're looking for some cache or data-store of already processed information. You could write a class to store this type specific info and then retrieve it in later calls to your virtual process functions. Something like:
class DataCache {
public:
void store( DerivedA* data );
void store( DerivedB* data );
std::list<DerivedA*>& getDerivedA();
std::list<DerivedB*>& getDerivedB();
}
Now your process function should take a reference to a DataCache object, so each call can store and get appropriately. DerivedB might implement process like:
DerivedB::process( DataCache& cache ) {
std::list<DerivedA*>& a_data = cache.getDerivedA();
//do something
cache.store( this );
}
I've interpreted your question as pertaining to reading in a file or stream which has a header section that sets out the subsequent instance definition sections.
#include <iostream>
class AbstractDataProcessor;
class ProcessorFactory
{
public:
static AbstractDataProcessor* create(const char id);
};
class AbstractDataProcessor
{
public:
AbstractDataProcessor() : next_(0) {}
virtual ~AbstractDataProcessor()
{
if(next_ != 0)
{
delete next_;
next_ = 0;
}
}
void process(const char* buf, int size)
{
process(buf, 0, size);
}
protected:
virtual int do_process(const char* buf, int start, int size) = 0;
void append(AbstractDataProcessor* chain)
{
if(next_ == 0)
{
next_ = chain;
}
else
{
next_->append(chain);
}
}
private:
void process(const char* buf, int start, int size)
{
int next_start = do_process(buf, start, size);
std::cout << "AbstractDataProcessor::process: start = " << start << " : size = " << size << " : next_start = " << next_start << std::endl;
if(next_ == 0 || next_start >= size)
{
return;
}
next_->process(buf, next_start, size);
}
AbstractDataProcessor* next_;
};
class HeaderProcessor : public AbstractDataProcessor
{
protected:
static const char header_sentinel = 'H';
virtual int do_process(const char* buf, int start, int size)
{
int current = start;
while(current < size && buf[current] != header_sentinel)
{
std::cout << "HeaderProcessor::do_process: buf[" << current << "] = " << buf[current] << std::endl;
AbstractDataProcessor* section_processor = ProcessorFactory::create(buf[current]);
if(section_processor != 0)
{
append(section_processor);
}
++current;
}
return current + 1;
}
};
class ElementProcessor : public AbstractDataProcessor
{
protected:
int do_process(const char* buf, int start, int size)
{
foo_ = static_cast<float>(buf[start]);
std::cout << "ElementProcessor::do_process: buf[" << start << "] = " << buf[start] << " : foo_ = " << foo_ << std::endl;
return start + (sizeof(float) / sizeof(char));
}
private:
float foo_;
};
AbstractDataProcessor* ProcessorFactory::create(char id)
{
std::cout << "ProcessorFactory::create: id = " << id << std::endl;
switch(id)
{
case 'h':
return new HeaderProcessor;
case 'e':
return new ElementProcessor;
default:
return 0;
}
}
int main(int argc, char** argv)
{
static const int buf_size = 6;
char testbuf[buf_size] = { 'e', 'H', 'x', '3', 't', '[' };
AbstractDataProcessor* testprocessor = ProcessorFactory::create('h');
testprocessor->process(testbuf, buf_size);
return 0;
}
its not the most elegant example, but it illustrates the idea of generating a linked list of processors that act on a single input stream of data. Each processor is capable of appending a new processor as appropriate, you could define another method "AbstractDataProcessor::insert" to allow for implementing a recursive delegation approach within each "do_process" method too. i haven't included any useful extraction methods, but it should be easy enough to walk the linked list and spit out pointers to something in main or wherever you need it.
You could do something like this:
class DerivedA;
class Base{
public:
virtual void Process();
protected:
static std::vector<DerivedA*> dependencies;
};
class DerivedA : public Base {
private:
char* structBuf;
public:
DerivedA() {
dependencies.push_back(this);
}
virtual void Process();
};
class DerivedB : public Base {
private:
char* structBuf;
public:
virtual void Process();
};
int main()
{
std::vector<Base*> allBase;
for(int i = 0 ; i < 10; i++) {
allBase.push_back(FactoryObject());
}
for(int i = 0 ; i < 10; i++) {
allBase[i]->Process();
}
return 0;
}
In short, while the objects are constructed the DerivedA ones are registering themselves in a static vector in Base, which means they are accessible in DerivedB once you are calling Process() on DerivedB types.
You must allow for all derived classes to be created before you can call Process. So, first map and create all and then map again and call Process(). This is of course not optimal since the base knows some about its inherited classes, but you insisted on having this factory pattern.
A better solution is to lift out the static vector from Base and store DerivedA elsewhere. But in the end it will boil down to you having to store DerivedA instances somewhere, and that registration should be done at construction, i.e. in the constructor of DerivedA. I dont know if a simple vector will do as registration, please modify this to suit your needs. For example you might want to look up DerivedA* with some identifier and need a hash or map instead.
Here comes dynamic_cast handy for you. If you have a Base* pointer, you try to do dynamic_cast. If it really is, then the result will be the DerivedA object. Else it is not DerivedA, returns NULL.
So in your main(),
Base* a = FactoryObject();
DerivedA *CheckObj= dynamic_cast<DerivedA*>(a);
DerivedA *AObj = NULL;
if(CheckObj)
{
AObj = CheckObj;
AObj->Process();
}
else
{
if(AObj)
{
AObj->Process();
CheckObj->Process();
}
}