Making an object belonging to a class depending on input parameters in C++ - c++

I'm trying to build an object which is of a type which depends on input parameters. E.g. my object is called 'process' and at runtime an integer between 2 and 5 (inclusive) is entered and something a bit like this would happen:
if (input == 2) TwoJ process;
if (input == 3) ThreeJ process;
if (input == 4) FourJ process;
if (input == 5) FiveJ process;
Obviously the above will not work because the object goes out of scope immediately. Is there a way to implement this nicely?
Cheers

Use a factory function that returns a smart pointer to a base Process class and whose implementation is determined by an integer value supplied to the factory function (requires that all classes have a common base).
For example:
class Base_process
{
public:
virtual ~Base_process() {}
virtual void do_something() = 0;
};
class TwoJ : public Base_process
{
public:
void do_something() {}
}
class ThreeJ : public Base_process
{
public:
void do_something() {}
}
std::unique_ptr<Base_process> make_process(int a_type)
{
if (a_type == 1) return std::unique_ptr<Base_process>(new TwoJ());
if (a_type == 2) return std::unique_ptr<Base_process>(new ThreeJ());
// Report invalid type or return an acceptable default if one exists.
throw std::invalid_argument("Unknown type:" + std::to_string(a_type));
}

A factory method of sorts
std::unique_ptr<ProcessType> CreateProcess(int input){
if(input == 2) return std::unique_ptr<ProcessType>(new TwoJ());
.....
}
This assumes, of course, that the various classes you use have a common base class, here ProcessType, and that you are satisfied with interacting with it via a base class pointer.

you can but, you need 1 base class for those all e.g.
Base* process;
if (input == 2) process = new TwoJ();
if (input == 3) process = new ThreeJ();
then to access those class all you need is:
if (input == 2) (TwoJ*)process->someTwoJMethod();
or by using dynamic_cast:
TwoJ* p = dynamic_cast<TwoJ*>(process);
if(p != 0) {
p->someTwoJMethod();
}
with this you own responsibility to delete your object once it's go out of scope.
The previous answers are the best way in cpp using std::unique_ptr the object will get deleted automatically when the object go out of scope.

Related

method of super-class called WHEN super has a str attr + instance of sub is created in a loop + instance is stored in a vector as a pointers of super

I can't reach a method of a sub-class' instance when several conditions are merged :
There is in the super-class an attribute of type string.
The instance have been created in a loop
The instance is stored in a vector that takes super-class pointers
It's so look like this :
class Parent
{
public :
string name;
virtual void myMethod() = 0;
};
class Child : public Parent
{
public :
void myMethod();
};
void Child::myMethod()
{
cout << "I'm a child";
}
int main(void)
{
vector<Parent*> children;
for(unsigned int i = 0 ; i < 1; i++ )
{
Child c;
children.push_back(&c);
}
(*children[0]).myMethod();
}
In that case the code over with an error : "pure virtual method called
terminate called without an active exception". I guess that it's trying to access to 'Parent::myMethod' that is virtual and so fail. To avoid that issue I can :
- Remove the attribute 'name' of the super-class
- Change the type of that attribute (to int for exemple)
- Append the elements to the vector from outside of the for loop.
I just can't figure what is going on in that specific case...
There is only one "condition" that matters here: the pointers you push in the vector point to garbage when Child c; goes out of scope:
{
Child c; // this object lives only in this scope !!
children.push_back(&c); // <-- &c is fine here
} // <-- already here it is not !
(*children[0]).myMethod(); // ***BOOM***
Maybe you got the impression that it is a specific combination of conditions to get the error, but thats just because dereferencing an invalid pointer is undefined behaviour, so sometimes it may look like it worked when actually it is never correct.

Java PriorityQueue implementation: Why Object[] queue instead of E[] queue? What's the purpose of "key" in siftUp/siftDownComparable?

I'm studying the JDK implementation of PriorityQueue.
1) The entire queue is stored in
transient Object[] queue;
Why not declare the array using the generic E? (Instead, there's a lot of casting E to objects in the class.)
2) The first line of the siftUpComparable/siftDownComparable methods is
Comparable<? super E> key = (Comparable<? super E>)x;
Is this a guard clause to verify that x is comparable? (Otherwise, why not just use x directly?)
Here's the entire method:
private void siftDownComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>)x;
int half = size >>> 1; // loop while a non-leaf
while (k < half) {
int child = (k << 1) + 1; // assume left child is least
Object c = queue[child];
int right = child + 1;
if (right < size &&
((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
c = queue[child = right];
if (key.compareTo((E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = key;
}
1) You cannot instantiate an array of a generic type without having a reference to the Class of the object. See JavaDevil's comment below for an example. However, by creating an array of Object's instead, there's is no requirement to feed an instance of the Class to the PriorityQueue.
E[] array = new E[10]; // won't compile
2) A PriorityQueue can sort its elements either by a Comparable's object compareTo() method or using a Comparator for objects that are not necessarily Comparable. The siftDownComparable method is only invoked if a Comparator was not provided when the PriorityQueue was created. Since the type parameter does not stipulate that <E extends Comparable>, you need to cast it explicitly. Here's the siftDown() method.
private void siftDown(int k, E x) {
if (comparator != null)
siftDownUsingComparator(k, x);
else
siftDownComparable(k, x);
}

Problems with nested object in functional object of the tbb::flow::graph

I have a functional object that I'm using as body for multifunction_node:
class module
{
private:
bool valid;
QString description;
bool hasDetectionBranch;
tDataDescription bufData;
void* dllObject; //<-- This is a pointer to an object constructed with help of the external dll
qint64 TimeOut;
public:
module(const QString& _ExtLibName);
virtual ~module();
void operator() (pTransmitData _transmitData, multi_node::output_ports_type &op);
};
'dllObject' is created at construction time of the object 'module':
module::module(const QString& _ExtLibName) :
valid(true), hasDetectionBranch(false)
{
GetObjectDescription = (tGetObjectDescription)QLibrary::resolve(_ExtLibName, "GetObjectDescription");
CreateObject = (tCreateObject)QLibrary::resolve(_ExtLibName, "CreateObject");
DestroyObject = (tDestroyObject)QLibrary::resolve(_ExtLibName, "DestroyObject");
if (!CreateObject || !DestroyObject || !GetObjectDescription)
valid = false;
else
{
description = QString(GetObjectDescription());
dllObject = CreateObject();
}
}
And this is when 'dllObject' is destroyed:
module::~module()
{
if (valid)
{
DestroyObject(dllObject);
}
}
I've built a little graph:
void MainWindow::goBabyClicked(void)
{
module mod(QString("my.dll")); //<-- Here is OK and mod.dllObject is correct
if (!mod.isValid())
{
qDebug() << "mod is invalid!\n";
return;
}
first fir(input);
folder fol(QString("C:/out"), 10000);
graph g;
source_node<pTransmitData> src(g, fir, false);
multi_node mnode(g, tbb::flow::serial, mod); //<-- WTF? ~module() is executed!
function_node<pTransmitData> f(g, tbb::flow::serial, fol);
make_edge(src, mnode);
make_edge(mnode, f);
src.activate();
g.wait_for_all();
}
So I have 2 questions:
1) Why ~module() is executed and how to prevent this?
2) How to keep pointer for nested object correctly?
UPDATE Added some dummy code to prevent destroying dllObject at first time like:
bool b = false;
module::~module()
{
if (valid && b)
{
DestroyObject(dllObject);
}
if (!b)
b = true;
valid = false;
}
Now it works as expected but looks ugly :/
Max,
I assume you have a typedef of multi_node which is similar to the one in the reference manual example.
The constructor for the multifunction_node has the following signature:
multifunction_node( graph &g, size_t concurrency, Body body );
The body object is copied during the parameter passing and also during the construction of the node, so there are two copies of mod created during construction (actually three, as an initial copy of the body is also stored for re-initializing the body when calling reset() with rf_reset_bodies). The destructor calls you are seeing are probably those used to destroy the copies.
The body object should also have a copy-constructor defined or be able to accept the default-copy-constructor to make copies of the body. I think the QString has a copy-constructor defined, but I don't know about fields like tDataDescription. (I thought we had covered the basic requirements for Body objects in the Reference Manual, but I am still looking for the section.) In any case, the Body class must be CopyConstructible, as it is copied multiple times.
Regards,
Chris

Selecting derived class based on function parameter

I have these classes:
class Base
{
private:
string name;
public:
void setName(string n);
string getName();
void toString();
}
and two classes derived from this:
class DerivedA : public Base
{
private:
int width;
public:
void setWidth(int w);
int getWidth();
}
and
class DerivedB : public Base
{
private:
int height;
public:
void setHeight(int h);
int getHeight();
}
Now to my question. My main looks like this:
int main()
{
Base* b;
string line;
... file loading ...
while(...)
{
s = cin.getline(file,10);
if(s == "w")
{
b = new DerivedA();
}
else if(s == "h")
{
b = new DerivedB();
}
while(...)
{
b->toString();
}
}
return 0;
}
This always terminates my app. I found out that the b->toString(); part might be the source of the problem, because of different scopes. But anyway, is there a way how can I do this? (I left out boring and unrelated parts of code.)
Base should have a virtual destructor and every function you intend to override should be declared virtual. Additionally, your main function needs some modifications:
int main()
{
Base* b = nullptr; // initialize your pointer
string line;
// ... file loading ...
while(std::getline(file, line)) // this should be your while loop for your file parsing
{
//s = cin.getline(file,10); // why??? you appear to be trying to pass your ifstream object into cin's istream::getline method ... this won't even compile!
// I'm assuming s is a std::string, and you pull it out of the line variable at some point ...
if(s == "w")
{
if (b != nullptr) // properly free your memory
{
delete b;
b = nullptr;
}
b = new DerivedA();
}
else if(s == "h")
{
if (b != nullptr) // properly free your memory
{
delete b;
b = nullptr;
}
b = new DerivedB();
}
while(...)
{
if (b != nullptr) // make sure b is valid!
{
b->toString();
}
}
}
return 0;
}
This always terminates my app. I found out that the b->toString();
part might be the source of the problem, because of different scopes.
But anyway, is there a way how can I do this?
To start off with, what you have posted will (likely) not even compile. cin.getline will attempt to read from standard input. Your comment indicates you are loading a file, so (assuming that file is an std::ifstream instance, cin.getline(file, 10) is attempting to call a function std::istream::getline(std::istream&, int), which does not exist. std::getline does what it appears you want to do here. Additionally, even if you are attempting to read from standard input, it should be std::getline(std::cin, s), not cin.getline(file, 10).
Moving on, the next area is your memory leaks. Those are easy enough to fix by 1) initializing b when it is declared, and 2) properly deleteing it before you leak memory. The null checks are not totally necessary (with an initialized b), since delete will check for NULL anyway, but I wrote them in there to illustrate a point: you should be managing your memory properly!
Next up, your if-else if-condition has the potential to not do anything (that is, b would be uninitialized at worse, or NULL at best). If you don't want to do anything for non-"s"/"h" inputs, that is fine, but then you must do the following item (which you should do anyway).
Finally, the issue that is likely causing your crash is not checking if b is valid before attempting to use it: b->toString();. If b is invalid or null, you are invoking undefined behavior. Your program may crash, call your grandmother, or order a pizza for the President ... all would be valid options, and non of them are what you really intended to do.

C++ Calling a function that resides in multiple classes

#define classAnum 2;
#define classBnum 3;
class Base
{
virtual int open()=0;
virtual int close()=0;
}
class A:public Base
{
virtual int open();
virtual int close();
};
class B:public Base
{
virtual int open();
virtual int close();
}
int main()
{
A classA[classAnum];
B classB[classBnum];
openAnyClass(1);
CloseAnyClass(2);
}
I want to achieve functionality like this.
openAnyClass(1);
CloseAnyClass(2);
these 2 functions should be able to call open() and close() from any of class A and B.
openAnyClass(1) would call the open() function of 1st object in the array of either classA or classB.
open() --> will have different implementation in class A and class B. and open() in classA may be called from multiple clients and max. no. of clients is # defined.
At a time only one open() from any of the classA or classB is called. I dont want to have several copies of the same code.
with just one function i want call open() of any of class A and any of client.
for Eg: in the below statement i want to call open() of class A of client1. the param to openAnyClass(int) indicates the client Id. This could also meant classB[1].open();
'openAnyClass(1) = classA[1].open();'
What is the best way of doing this?
This is the reason for having a command base class that you derive from; that way you can have a pointer or reference to a class and call the open/close method in the derived classes via the virtual functions.
So if you had
Base *generic_class_pointer = new class A();
generic_class_pointer->open();
The generic_class_pointer->open() would invoke the code defined in class A.
What you're trying to do with two arrays that store objects, one for classes A and one for classes B is not required, you can have a single array that refers to classes of type Base and access via this.
The original code is not really a good way of working, it's better to do this via a list (eg. stl::vector).
Base* class_storage[StorageSize];
int openAnyClass(int id)
{
if (id < 0 || id >= StorageSize || class_storage[id] == 0)
return 0; // or other error indication
else
return class_storage[id]->open();
}
int CloseAnyClass(int id)
{
if (id < 0 || id >= StorageSize || class_storage[id] == 0)
return 0; // or other error indication
else
return class_storage[id]->close();
}
int main()
{
memset(class_storage,0,sizeof(class_storage));
class_storage[1] = new A();
class_storage[2] = new B();
openAnyClass(1);
CloseAnyClass(2);
}
The above code isn't a complete solution, for example the original doesn't have virtual destructors which is a good practice to always use - in case a derived class needs to do cleanup.
Also the deletion of the objects allocated into the class_storage isn't freed on my sample. It doesn't matter at global level because they will be freed upon exit, however most of the time you need to manage everything acquired via new() otherwise you'll get memory leaks.
so classA is an array of A, and same for classB. and calling openAnyClass(1), means call open() on all instances of A, and closeAnyClass() means call close() on all instances of classB. well if this is the case, the question is really complicated formulated
anyways there's no no known out of the box method to do that. you have to iterate on all elements of the array and call open() or close(). alternatively you can use boost foreach
http://www.boost.org/doc/libs/1_39_0/doc/html/foreach.html
or implement your own foreach method
If I understand your question correctly, you want to call different implementations of a pure virtual function. Assuming you have provided implementations of class A and class B, you should be able to make use of polymorphism and call open()/close() from a pointer/reference to a Base instead of A or B.
Instead of creating two arrays for A and B, you can create only one array of Base pointers.
Example:
Base* base[basenum];
void openAnyClass( const int i )
{
if( i < basenum && i >=0 && base[i] != NULL )
base[i]->open();
}
int main(void)
{
base[0] = new A();
base[1] = new B();
...
openAnyClass(1);
closeAnyClass(2);
for( int i = 0 ; i < basenum ; i++ )
delete base[i];
}
As a side note, I think it would be better to make use of open and close functions like these:
void openAnyClass( Base& base );
void closeAnyClass( Base& base );
Rather than using a global variable to store the objects and passing an index, pass the pointer/reference of the object to the function and the function would call the appropriate method(whether the method of A or B).