I have the below code (eg):
void Foo(int ip_selector)
{
ipv4_hdr_t ipv4;
ipv6_hdr_t ipv6;
{
…
if(ip_selector == 0)
addStack(ipv4);
else
addStack(ipv6);
}
{
…
if(ip_selector == 0)
addStack(ipv4);
else
addStack(ipv6);
}
…
}
int main()
{
for (int i = 0; i < 2; i++) {
Foo(i);
}
}
In the above code, addStack param depends on the selector param in Foo(). The above code works fine, but does to the scale it can grow, I do not want to add if ip_selector check everywhere in Foo() to see which arg to be passed in addStack(). I am trying to find a way to select either ipv4_hdr_t/ipv6_hdr_t without writing an if else condition. Infact, I dont even need the ipv6 declaration of ip_selector is 0 (vice versa for that matter)
here is one way to solve such a problem.
1.have a base class for your protocols, say Protocol.
2.derive your ip4/ip6/whateverelse classes from the base class.
3.create an array of available protocols.
4.use the selector to pick an array element.
class Protocol {
virtual void addStack() = 0;
...
};
class Ip4Protocol : public Protocol {
ip4_hdr_type hdr;
void addStack(){...}
};
vector<Protocol*> availableProtocols = {
new Ip4Protocol(),
new IP6Protocol(),
...
};
...
for (int i = 0; i < availableProtocols.size(); i++) {
avalableProtocols[i]->addStack();
}
or you can probably use templates on the derived classes as well
termplate <class P> class IP : public Protocol {
P hdr;
void addStack() {addGlobalStack(hdr)};
}
ther are tons of other possibilities as well.
Related
I am using typeid in my code, but it seems to me that the code can be cleaner if I avoid typeid.
If we want to store the type of the class, why would we choose an object-oriented language in the first place?
But I see this pattern over and over again and I do not know how to avoid it.
So I am thinking if this code can be written cleaner with a better abstraction?
Here is the code:
class A {
public:
string type;
};
template <typename T>
class B : public A {
public:
B() {
type = typeid(T).name();
}
};
class Registry {
private:
std::vector<A *> list;
public:
void append(A * a) {
int found = 0;
for (A * el : list) {
if (a->type == el->type) {
found = 1;
break;
}
}
if (!found)
list.push_back(a);
}
int size() {
return list.size();
}
};
int main(int argc, char **argv) {
Registry reg;
A * b_int1 = new B<int>();
A * b_int2 = new B<int>();
A * b_float = new B<float>();
reg.append(b_int1);
reg.append(b_int2);
reg.append(b_float);
cout << reg.size() << endl;
return 0;
}
The output is 2. (which is the expected result)
Basically we do not want to store two object of the same type in a list.
If you don't want visitors, but you'd like a quick RTTI, I'd suggest looking into this paper: http://www.stroustrup.com/fast_dynamic_casting.pdf
The idea is:
Each class is assigned a distinct prime number for it's own type (e.g., A::my_type = 2; B::my_type = 3)
Then each class is additionally assigned the product of its type and base class values if any (e.g., A::can_cast = A::my_type; B::can_cast = B::my_type * A::can_cast; )
This solves the is_same_dynamic(), is_base_dynamic() problems elegantly: former becomes ==, latter becomes %.
To check whether or not an object belongs to a class derived from a given class, one might use the dynamic_cast<T*> and compare the result with nullptr. Unfortunately, given that we need to check this fact to the unknown type, we are forced to implement such comparison method once per each descendant of class A, but this may be simplified using #define.
Summing up, I would probably write it like this:
#define TYPE_COMPARISON \
virtual bool compare(A* rhs) \
{ \
return dynamic_cast<decltype(this)>(rhs) != nullptr; \
}
class A {
public:
TYPE_COMPARISON
};
template <typename T>
class B : public A {
public:
TYPE_COMPARISON
};
class Registry {
private:
std::vector<A *> list;
public:
void append(A * a) {
int found = 0;
for (A * el : list) {
if (a->compare(el) && el->compare(a)) {
found = 1;
break;
}
}
if (!found)
list.push_back(a);
}
int size() {
return list.size();
}
};
Also, such method allows you to define whether or not a particular descendant class should be treated as being distinct with its parent.
This is a follow-up to this question. Someone asked about a minimal example, but I found it impossible to condense it all into something working. I still have issues, so I hope that by giving a bit more structure I can get some idea of what I am doing wrong or what I should be doing.
The classes I use form a tree structure, like this:
struct Base
{
/* nodeType is a number uniquely assigned to each concrete class */
int nodeType;
int numberOfA;
int numberOfB;
int NumberOfC;
int numberOfD;
AdvancedA** A_array;
AdvancedB** B_array;
AdvancedC** C_array;
Intermediate1** D_array;
virtual Base clone() = 0;
}
struct Intermediate1 : Base
{
}
struct Intermediate2 : Base
{
}
struct Advanced_A : Intermediate1
{
/* There might be different signatures since arguments might be
* real-valued, complex, or even matrices
*/
virtual double compute(signature 1);
virtual double compute(signature 2);
}
struct Advanced_B : Intermediate1
{
virtual std::complex compute(signature 1);
virtual std::complex compute(signature 2);
}
struct Advanced_C : Intermediate2
{
virtual matrix compute(signature 1);
//for example; definition of matrix class is not shown
}
struct Instance_A1 : Advanced_A
{
}
struct Instance_A2 : Advanced_A
{
}
...
struct Instance_B1 : Advanced_B
{
}
...
struct Instance_C1 : Advanced_C
{
}
...
I use these objects to build expression trees, which can evaluate to different types, corresponding to the three Advanced types. (Think of them as real-valued, complex-valued and matrix-valued expressions.) Because I need to evaluate the expressions, I have created three different types of expression trees, as follows.
struct BasicTree
{
virtual void cloneTree();
}
struct TreeType_A : BasicTree
{
Advanced_A* root;
}
struct TreeType_B : BasicTree
{
Advanced_B* root;
}
struct TreeType_C : BasicTree
{
Advanced_C* root;
}
I hope to eventually be able to use these in this manner:
TreeType_A* tree_A;
TreeType_B* tree_B;
TreeType_C* tree_C;
TreeType_A* copy_A;
TreeType_B* copy_B;
TreeType_C* copy_C;
copy_A = tree_A->cloneTree();
copy_B = tree_B->cloneTree();
copy_C = tree_C->cloneTree();
tree_A->root->compute(signature 1);
tree_B->root->compute(signature 1);
tree_C->root->compute(signature 2);
I have two concerns: The cloning of the array of Advanced elements will have to also clone the descendants. At the moment I put his into the method itself:
Base* Instance1::clone()
{
Base* temp = new Instance1();
(clone local stuff)
for (int i = 0; i < numberOfA; i++)
temp->A_array[i] = this->A_array[i]->clone();
for (int i = 0; i < numberOfB; i++)
temp->B_array[i] = this->B_array[i]->clone();
for (int i = 0; i < numberOfA; i++)
temp->C_array[i] = this->C_array[i]->clone();
for (int i = 0; i < numberOfD; i++)
temp->D_array[i] = this->D_array[i]->clone();
return temp;
}
If possible I would actually prefer to write a method cloneChildren that takes care of the recursion transparently.
Mostly I want to avoid having to use explicit casting. Different instances of the Advanced classes have different content, and this content seems to get lost if I try to write, e.g.
temp->A_array[i] = ((Advanced_A*)this->A_array[i])->clone();
On the other hand, using a long case statement based on the particular instance seems inefficient. So it seems I need to rely on automagic.
If further simplifications are possible, such as collapsing everything into a single tree type, or a single array of children, that would be great. (I doubt the former will work, because the compute functions need to look different and return different values for each type of root. The latter seems more promising to me.)
What other pitfalls might there be?
Given a class, I would like to limit the number of objects created from this class to a given number, say 4.
Is there a method to achieve this?
The basic idea is to count the number of created instances in some static variable. I would implement it like this. Simpler approaches exist, but this one has some advantages.
template<class T, int maxInstances>
class Counter {
protected:
Counter() {
if( ++noInstances() > maxInstances ) {
throw logic_error( "Cannot create another instance" );
}
}
int& noInstances() {
static int noInstances = 0;
return noInstances;
}
/* this can be uncommented to restrict the number of instances at given moment rather than creations
~Counter() {
--noInstances();
}
*/
};
class YourClass : Counter<YourClass, 4> {
}
You're looking for the instance manager pattern. Basically what you do is restrict instantiations of that class to a manager class.
class A
{
private: //redundant
friend class AManager;
A();
};
class AManager
{
static int noInstances; //initialize to 0
public:
A* createA()
{
if ( noInstances < 4 )
{
++noInstances;
return new A;
}
return NULL; //or throw exception
}
};
A shorter way is throwing an exception from the constructor, but that can be hard to get right:
class A
{
public:
A()
{
static int count = 0;
++count;
if ( count >= 4 )
{
throw TooManyInstances();
}
}
};
I'm trying to modify some variables [not necessary from the same class/struct] from keyboard's shortcuts, something like that:
A foo struct containing variables:
struct Foo {
int a;
float b;
};
struct Foo2 {
int c;
};
And a main like:
int main() {
Foo f;
Foo2 f2
void* p = &(f.a); //it could be &(f2.c)
if ('A' key activated) {
*p += 1;
}
}
Currently, I'm stucked at this point:
error: invalid operands to binary expression ('void' and 'int')
The only way to make it work is to change:
*p += 1;
By:
*(int*)p += 1;
Which is not a good solution, because I should not know the type pointed by p. Is there a way to do that?
Converting the pointer to void* lost the type information and the compiler will not know how to increment. Why don't you make a pointer to Foo instead?
int main() {
Foo f;
Foo* p = &f;
if ('A' key activated) {
p->a += 1;
}
}
Also keep in mind that incrementing a float is not a good idea!
For the quesion in the comment of this answer:
struct FooBar
{
int *a;
float *b;
};
int main() {
Foo f;
Bar b;
FooBar fb{&f.a, &b.b};
if ('A' key activated) {
*(fb.a) += 1;
}
}
Note that this solution is rather C-style. Look at lethal-guitar's answer for a more C++-style solution.
Edit: At first I didn't realize that you want to have different types per entry. Based on the task of handling keyboard shortcuts, you could use a polymorphic class, and put instances of it into a std::map:
class KeyHandler {
public:
virtual void onKeyStroke() = 0;
};
class MyHandler : public KeyHandler {
public:
MyHandler(int& value) : myValue(value) {}
virtual void onKeyStroke() {
myValue_ += 1;
}
private:
int& myValue_; // Other subclasses could have other data
};
// Now place instances of different Handlers into a std::map
typedef std::shared_ptr<KeyHandler> PKeyHandler;
std::map<char, PKeyHandler> bindings;
bindings['A'] = PKeyHandler(new IncrementIntHandler(&someInt));
bindings['B'] = PKeyHandler(new IncrementFloatHandler(&someFloat));
// The actual input handler then just invokes
// the correct handler for a key stroke.
bindings[keyCode]->onKeyStroke();
That way, you can define a handler class for every action you want to support, and implement the corresponding logic into these classes. You could make the base class' implementation just do nothing to handle non-mapped keys, etc.
Sure, use an int pointer instead:
int * p = &f.a;
if ( /* condition */ ) { ++*p; }
I'm writing an xml parser and I need to add objects to a class generically, switching on the actual type of the object. Problem is, I'd like to keep to an interface which is simply addElement(BaseClass*) then place the object correctly.
void E_TableType::addElement(Element *e)
{
QString label = e->getName();
if (label == "state") {
state = qobject_cast<E_TableEvent*>(e);
}
else if (label == "showPaytable") {
showPaytable = qobject_cast<E_VisibleType*>(e);
}
else if (label == "sessionTip") {
sessionTip = qobject_cast<E_SessionTip*>(e);
}
else if (label == "logoffmedia") {
logoffMedia = qobject_cast<E_UrlType*>(e);
}
else {
this->errorMessage(e);
}
}
This is the calling class, an object factory. myElement is an instance of E_TableType.
F_TableTypeFactory::F_TableTypeFactory()
{
this->myElement = myTable = 0;
}
void F_TableTypeFactory::start(QString qname)
{
this->myElement = myTable = new E_TableType(qname);
}
void F_TableTypeFactory::fill(const QString& string)
{
// don't fill complex types.
}
void F_TableTypeFactory::addChild(Element* child)
{
myTable->addElement(child);
}
Element* F_TableTypeFactory::finish()
{
return myElement;
}
void F_TableTypeFactory::addAttributes(const QXmlAttributes &attribs) {
QString tName = attribs.value(QString("id"));
myTable->setTableName(tName);
}
Have you considered using polymorphism here? If a common interface can be implemented by each of your concrete classes then all of this code goes away and things become simple and easy to change in the future. For example:
class Camera {
public:
virtual void Init() = 0;
virtual void TakeSnapshot() = 0;
}
class KodakCamera : Camera {
public:
void Init() { /* initialize a Kodak camera */ };
void TakeSnapshot() { std::cout << "Kodak snapshot"; }
}
class SonyCamera : Camera {
public:
void Init() { /* initialize a Sony camera */ };
void TakeSnapshot() { std::cout << "Sony snapshot"; }
}
So, let's assume we have a system which contains a hardware device, in this case, a camera. Each device requires different logic to take a picture, but the code has to support a system with any supported camera, so we don't want switch statements littered throughout our code. So, we have created an abstract class Camera.
Each concrete class (i.e., SonyCamera, KodakCamera) implementation will incluse different headers, link to different libraries, etc., but they all share a common interface; we just have to decide which one to create up front. So...
std::unique_ptr<Camera> InitCamera(CameraType type) {
std::unique_ptr<Camera> ret;
Camera *cam;
switch(type) {
case Kodak:
cam = new KodakCamera();
break;
case Sony:
cam = new SonyCamera();
break;
default:
// throw an error, whatever
return;
}
ret.reset(cam);
ret->Init();
return ret;
}
int main(...) {
// get system camera type
std::unique_ptr<Camera> cam = InitCamera(cameraType);
// now we can call cam->TakeSnapshot
// and know that the correct version will be called.
}
So now we have a concrete instance that implements Camera. We can call TakeSnapshot without checking for the correct type anywhere in code because it doesn't matter; we know the correct version for the correct hardware will be called. Hope this helped.
Per your comment below:
I've been trying to use polymorphism, but I think the elements differ too much. For example, E_SessionTip has an amount and status element where E_Url just has a url. I could unify this under a property system but then I lose all the nice typing entirely. If you know of a way this can work though, I'm open to suggestions.
I would propose passing the responsibility for writing the XML data to your types which share a common interface. For example, instead of something like this:
void WriteXml(Entity *entity) {
switch(/* type of entity */) {
// get data from entity depending
// on its type and format
}
// write data to XML
}
Do something like this:
class SomeEntity : EntityBase {
public:
void WriteToXml(XmlStream &stream) {
// write xml to the data stream.
// the entity knows how to do this,
// you don't have to worry about what data
// there is to be written from the outside
}
private:
// your internal data
}
void WriteXml(Entity *entity) {
XmlStream str = GetStream();
entity->WriteToXml(stream);
}
Does that work for you? I've done exactly this before and it worked for me. Let me know.
Double-dispatch may be of interest. The table (in your case) would call a virtual method of the base element, which in turns calls back into the table. This second call is made with the dynamic type of the object, so the appropriate overloaded method is found in the Table class.
#include <iostream>
class Table; //forward declare
class BaseElement
{
public:
virtual void addTo(Table* t);
};
class DerivedElement1 : public BaseElement
{
virtual void addTo(Table* t);
};
class DerivedElement2 : public BaseElement
{
virtual void addTo(Table* t);
};
class Table
{
public:
void addElement(BaseElement* e){ e->addTo(this); }
void addSpecific(DerivedElement1* e){ std::cout<<"D1"; }
void addSpecific(DerivedElement2* e){ std::cout<<"D2"; }
void addSpecific(BaseElement* e){ std::cout<<"B"; }
};
void BaseElement::addTo(Table* t){ t->addSpecific(this); }
void DerivedElement1::addTo(Table* t){ t->addSpecific(this); }
void DerivedElement2::addTo(Table* t){ t->addSpecific(this); }
int main()
{
Table t;
DerivedElement1 d1;
DerivedElement2 d2;
BaseElement b;
t.addElement(&d1);
t.addElement(&d2);
t.addElement(&b);
}
output: D1D2B
Have a Look at the Visitor Pattern, it might help you