class OSwitch {
private:
Operator *operators[];
//int variable; <-- unused variable
public:
OSwitch() {}
~OSwitch() {}
void setOperator(int id, Operator *op) {
operators[id] = op;
}
void execute(int id) {
operators[id]->execute();
}
};
There are several subclasses of the abstract baseclass Operator.
When calling setOperator() for more than one time, the array "forgets" the last element.
for example
XOperator a;
YOperator b;
os.setOperator(1,a);
os.setOperator(2,b);
os.execute(1); // <- wont work
But when the int variable (or any other variable in OperatorSwitch) is declared, it works.
I dont have any idea how this works.
Thanks for any hint.
Your member variable operators is an unsized array, which is an incomplete type and not allowed in a class definition.
What you probably want instead is a map of integers to pointers:
#include <map>
class OSwitch
{
private:
std::map<int, Operator *> operators;
public:
void setOperator(int id, Operator *op) { operators[id] = op; }
void execute(int id) { operators[id]->execute(); }
};
Note that it will be an error to call execute on an ID that has not been assigned a valid pointer. You can make this more robust by checking for existence of the map element first.
Array operators doesn't have a size declared. Either declare the number of elements in the array, as in operators[10], or use std::vector instead.
You need to initialize the array before adding data.
I would recommend you to work with values, not pointers, in this array, because then you won't have problems defining who will delete the Operator*s afterwards (i.e. the caller of setOperator or ~OSwitch()).
Related
I've been working on a C++ project for school and I've encountered some problems when it comes to 2D arrays of objects. So I have the following class:
class mecanice
{
public:
mecanice();
~mecanice();
...
protected:
private:
...
MyClass Ob[8][8];
};
And I need a method that will return Ob so that I can use it in a method from some other class that will do stuff based on what's in Ob:
class doodle
{
public:
doodle();
~doodle();
void do_stuff(MyClass M[8][8]);
...
protected:
private:
...
};
I've tried all kinds ways of going about it but all of them ended up with compiling errors usually related to pointers. Is there any way to do this?
Try the following
const MyClass ( * myMagicMethod() )[8] const;
Or
typedef const MyClass ( *A )[8];
//...
A myMagicMethod() const;
The qualifier const is used if you do not want that the array would be changed in a method of other class.
Another approach is to pass the array by reference. For example
const MyClass ( & myMagicMethod() )[8][8] const;
Or
typedef MyClass ( &A )[8][8];
//...
const A myMagicMethod() const;
In the method that will process the array the parameter also must be declared like reference.
You cannot return arrays from functions. In your case, a function that looks like:
MyClass[][] bar ();
is ill-formed.
You can consider to have that function take MyClass[][] as a parameter, instead of returning it as a return value, and filling it appropriately.
void bar (MyClass foo[8][8]);
You can also return a pointer instead (which is legal):
MyClass** bar () { }
But you will have to make sure that the memory of the object you are returning a pointer to is persistent (i.e. do not return a pointer to a local variable, etc...).
I am coming from the Java background. I have the following program.
#include <string>
#include <iostream>
class First {
public:
First(int someVal): a(someVal) {
}
int a;
};
class Second {
public:
First first;
Second() { // The other option would be to add default value as ": first(0)"
first = First(123);
}
};
int main()
{
Second second;
std::cout << "hello" << second.first.a << std::endl;
}
In class Second, I wanted to variable first to remain uninitialized until I specifically initialize it in Second()'s constructor. Is there a way to do it? Or am I just left with 2 options?:
Provide a parameter-less constructor.
Initialize it with some default value and later re-assign the required value.
I can't initialize first in the initializer-list with the right value, since the value is obtained after some operation. So, the actual required value for first is available in Second() constructor only.
MY suggestion: Use a function:
private: static int calculate_first(int input) {return input*5;}
explicit Second(int input) : first(calculate_first(input)) {}
Base classes will be initialized in the order they're declared in the class inheritance list, and then members will be initialized in the order that they're listed in the class, so the calculation can depend on non-static member-variables and base classes if they have already been initialized.
Alternatively:
Default constructor, then reassign:
explicit Second(int input) { first = input*5; }
Dummy value, then reassign:
explicit Second(int input) : first(0) { first = input*5; }
Use boost::optional (or std::optional as of C++17):
boost::optional<First> first;
explicit Second(int input) { first = input*5; }
Use the heap:
std::unique_ptr<First> first;
explicit Second(int input) { first.reset(new First(input*5));}
Second(const Second& r) first(new First(*(r->first))) {}
Second& operator=(const Second& r) {first.reset(new First(*(r->first)));}
Placement new:
This is tricky and not suggested
and worse in every way than boost::optional
So sample deliberately missing.
But it is an option.
Initialize first in the member initializer list.
It may help to perform your calculations in a helper function and use a forwarding constructor:
class Second {
public:
Second() : Second(helper_function()) {}
private:
Second(int calc): first(calc) {}
static int helper_function() { return ...; }
First first;
};
This sentence is the core of the problem:
I can't initialize first in the initializer-list with the right value,
since the value is obtained after some operation.
You should know that what you want to do here is not perfect programming style in Java, either. Leaving the field with some default value and then assigning it a bit later after some calculations have been done effectively prevents it from being final, and consequently the class from being immutable.
In any case, your goal must be to push those calculations directly into the initialization of the member, using private helper functions (which may be static):
class Second {
private:
First first;
static int getInitializationData()
{
// complicated calculations go here...
return result_of_calculations;
}
public:
Second() : first(getInitializationData()) {}
};
In my opinion, everything else is just a workaround and will complicate your life in the long run.
You can just do what you said in the comments, or, you can make first a pointer to First and give it memory whenever you like, although i don't recommend this way
One way to separate object lifetimes is to use the heap, make first a pointer and initialize it anytime you like:
class Second {
public:
First* first;
Second() {
first = new First(123);
}
};
of course, you'll probably want to use a smart pointer of some sort rather than a raw pointer.
If you don't code to explicitly initialize a member variable, the default initializer is used to initialize it.
The draft C++ standard has the following about initialization of base classes and member variables:
12.6 Initialization [class.init]
1 When no initializer is specified for an object of (possibly cv-qualified) class type (or array thereof), or the initializer has the form (), the object is initialized as specified in 8.5.
And
12.6.1 Explicit initialization [class.expl.init]
1 An object of class type can be initialized with a parenthesized expression-list, where the expression-list is construed as an argument list for a constructor that is called to initialize the object. Alternatively, a single assignment-expression can be specified as an initializer using the = form of initialization. Either direct-initialization semantics or copy-initialization semantics apply; see 8.5.
I want to create an array in class hash and use it in its methods. I tried declaring it in public but still other methods are not able to access it.
Here is my class declaration:
class hash
{
public:
string hash_table[size]; //size is global variable;
void initialize(int,string*,int); //I pass `hash_table` pointer and two other `int` type //arguments.
int hash_function(string, int);
void quad_prob(int, int, string* , string); //`hash_table` array is used in this method also.
void print(string*); //to print `hash_table` array
};
I have to use array only.
Also, can pleas explain when I use hash h; in int main(), what happens?
Here is complete code (without using class structure) : http://codepad.org/DQggdoI6
It looks like you are trying to convert existing code to a class, yes? Keep your string hash_table[] private in the class. Then remove that parameter from each of the functions on codepad. So initialize, as folks have pointed out, becomes the constructor hash(int n, int size) and initializes hash_table (hash_table = new string[size] or some such). Similarly, print becomes just plain print(), and can refer directly to hash_table since it's a member function of the hash class.
your array will be initialized when you create a new hash object. You would use hash h before any code using the object. When you make a new object, your constructor sets up your object for later use in your code. From there you should be able to use your code from your class.
first I would suggest you use a vector.
Secondly once its defined in your class you just access it by name.
class foo
{
public:
foo(): vecfoo(5)
{}
void DoSomeThing()
{
for_each(begin(vecfoo),end(vecfoo),[](const string &){...});
}
private:
vector<string> vecfoo;
};
I would like to know if it'd be possible (and if, how) to create a pointer of X value
Now, let's say I know which types would be possible to be assigned in this pointer.
For example, a pointer of X value (of course feel free to change the name of this value), that'd be able to point to variables of string, bool and a custom class
Usually what you describe is a bad idea.
void* works, for marginal values of works. It throws out all type safety, requiring you to keep track of it.
Creating a root type sort of works, but it doesn't work for primitive types, and is rather intrusive.
A boost::variant< bool*, std::string*, MyClass* > is a variable that can contain a pointer to any one of these 3 types (bool, std::string or MyClass). You will probably find it challenging to use, because it enforces type safety, and the syntax can get annoying.
Similarly, a pointer to boost::variant< bool, std::string, MyClass > may be what you want, but it doesn't let you point to bool variables you aren't fooling around with.
With full C++11 support, union can contain arbitrary types, together with an enum can let you do something very much like a boost::variant. As a downside, this requires the thing you be pointed to be a union. With or without full C++11 support, a union of pointers is reasonable. In both cases, you'll have to track the type manually and keep it in sync.
What you really need to think about is "why am I asking this?", because as with many questions, the motivation matters. You may not be asking the right question.
I learned a new expression today, so I'm going to use it, "This is an XY question", You want to do X, so you think the solution is Y, therefore you ask how to do Y. You PROBABLY should ask how to do Y instead. It's a bit like you find your front wheel on the car punctured, and you go talk to the mechanic, but you don't ask "how do I fix a puncture", you ask "How do I undo a wheelnut", and only after you've removed all wheelnuts and the car has fallen over do you realize that you should have put a jack under the car to be able to get the wheel off without the car falling over...
Sure, there are void pointers and unions, that's no big deal. However, you still need to know what your pointer is actually pointing at, otherwise you'll have bloody mess.
So generally, in C++, you probably shouldn't do that.
What you should do is wrap your "thing" in another object, that knows what the content is, and can handle it. That way, you don't have some other thing maintainng state of what the object is and how to use it.
For example, we can have this:
class AnyThing
{
public:
virtual ~AnyThing();
virtual std::string ToString() = 0;
... // other things you want to do with your "things".
};
class IntThing: public AnyThing
{
private:
int value;
public:
virtual std::string ToString() { ... convert int to string ... }
};
class StringThing : public Anything
{
private:
std::string value;
public:
virtual std::string ToString() { return value; }
}
You can use a pointer to void.
If you want a pointer that can only be used to point at those three types, then I see three options:
Create a wrapper class for each type that derives from some base-class:
class Thingy { protected: Thing() {} };
class BoolThingy : public Thingy { bool x; }
class StringThingy : public Thingy { String x; }
class CustomThingy : public Thingy { Custom x; }
...
Thingy *p = new BoolThingy;
Create a smart-pointer class, overloading assignment operators that take bool *, String *, Custom *, and also overloading the * operator (although what that would do, I don't know!)
Use a variant class (e.g. boost::variant).
But with any of the options, it's not clear how such a thing would be useful...
void* has the property to point to any data type. It actually works as a container or cubboard in which you put your variable of any data type and then pass the void* to a function.
You must know the data type of the data you passed, in order to use it.
For Example:
int main()
{
int a;
void *x=&a;
func(x);
....
}
void func(void *argument)
{
int i=*(int *)argument;
....
}
If you know the types before hand and they do not have constructors. Then you can use a union.
class CustomClass {};
union MyType
{
char const* a;
bool b;
float c;
};
MyType stuff;
MyType* ptrToStuff = &stuff;
int main()
{
ptrToStuff->a = "Plop";
ptrToStuff->b = false;
ptrToStuff->c = 12.0;
}
Boost also has an ANY type.
You can store anything in it.
boost::any x = 12;
x = new CustomClass;
x = new std::string("Hi There");
x = std::string("Plop"); // even works without pointers.
You can have a pointer to any type (object, pointer, primitive type etc.) but you can not have a pointer to a reference.
NO you cannot have a pointer pointing at objects of unspecified type. The whole point of a pointer is that it points at objects of specific type. int*x points at an int, A*a points at an A.
What you can do, of course, is to have a variable of type void* that points at nothing at all (void), but can hold any address. If you somehow remember what it is the address of, then you can use a static_cast<> to cast to an appropriate pointer. Alternatively, you can use dynamic_cast<> to find out at run-time whether your void* points to a given type. This could be implemented as follows
struct AnyPointerWrapper
{
struct null_pointer {};
struct wrong_pointer_type {};
AnyPointerWrapper() : ptr(0) {}
AnyPointerWrapper(AnyPointerWrapper const&) = default;
AnyPointerWrapper&operator=(AnyPointerWrapper const&) = default;
template<typename T>
explicit AnyPointerWrapper(T*p)
: ptr(p) {}
template<typename T>
AnyPointerWrapper&operator=(T*p)
{ ptr=p; return*this; }
bool is_null() const
{ return ptr==0; }
template<typename T>
bool is() const
{ return dynamic_cast<T*>(ptr) != 0; }
template<typename T>
T* pointer()
{
if(p==0) throw null_pointer;
T*p = dynamic_cast<T*>(ptr);
if(p==0) throw wrong_pointer_type;
return p;
}
private:
void*ptr;
};
and used like this
int X;
AnyPointerWrapper a;
assert(a.is_null());
a = &X;
assert(a.is<int>());
int*p = a.pointer<int>();
(you can add more functionality including support for const pointers). Note, however, that the dynamic_cast<> is not trivial, i.e. incurs some performance penalty. Note also that AnyPointerWrapper is not a pointer: you cannot use the -> operator to call a member function of the object whose address is stored in AnyPointerWrapper::ptr; it is merely a wrapper from which you can get an appropriate pointer.
I posted earlier today about template classes, but was pretty far off and got a solution to my previous problem from here. Of course when that's dealt with, there's always a new one that I can't seem to figure out.
Given the following constructor:
template <typename Type, int inSize>
sortedVector<Type, inSize>::sortedVector():
size(inSize), vector(new Type[inSize]), amountElements(0)
{}
I want to make a dynamic array, which I then can insert elements of whatever type into via an add-method. The calls from main will look as follows:
sortedVector<Polygon, 10> polygons;
sortedVector<int, 6> ints;
How can I initialize the array to zero when it's constructed? I can not set an object to zero ;)
I thought I was being smart and tried to overload the =-operator for Polygon and given an int it would do nothing. Turns out I can not do that ):
Any good suggestions?
Also, here's the template class sortedVector:
template <typename Type, int inSize>
class sortedVector
{
public:
sortedVector();
int getSize();
int getAmountElements()
bool add(const Type &element);
private:
Type *vector;
int size;
int amountElements;
};
and just in case also Polygon:
class Polygon
{
public:
Polygon();
Polygon(Vertex inVertArr[], int inAmountVertices);
~Polygon();
void add(Vertex newVer);
double area();
int minx();
int maxx();
int miny();
int maxy();
int getAmountVertices() const;
friend bool operator > (const Polygon &operand1, const Polygon &operand2);
friend bool operator < (const Polygon &operand1, const Polygon &operand2);
private:
Vertex *Poly;
int amountVertices;
};
Initialize the array elements to Type(). This is what the standard library containers do. For built-in numeric types, Type() is equivalent to 0. For class/struct types, Type() constructs a temporary default-constructed object.
You can just use Type() to get a default constructed object. A better approach is to use std::vector<T> either directly or via a thin wrapper adding whatever functionality or constraints are needed. Although it is doable without std::vector<T> any solution which actually properly manages resources and objects will end up reimplementing at least parts of std::vector<T>.
Just assign every element of the "vector" (confusing name, by the way, given the prominence of std::vector<>) to the default value. The default value is just Type(), so you'd do something like this in the constructor body:
std::fill(vector, vector + size, Type());
How can I initialize the array to zero when it's constructed? I can
not set an object to zero ;)
You can use so-called default constructed value. In other words, you need to define (if it is not defined) special value that will play role of zero for your object.