The field has to be immutable so I can't use the vector. Is there a way to do it like in the title?
I want to do something like this:
typedef list<pair<int,string>> list_pair;
class tree{
private:
list_pair arr[]{
public:
tree(int size){
arr[size];
}
}
Is there a way to do it like in the title?
No.
A non-static member array must have a known size, there is no way around that in C++.
The field has to be immutable so I can't use the vector.
Your example array of non-const isn't immutable either.
Furthermore, I don't see a reason why that should matter. It's a private member, so it's fairly easy to choose to not mutate it. That way the class remains effectively immutable from the outside. Conclusion: Use std::vector.
Related
I am trying to solve the Conway's game of life in c++. So according to my design, I have a cell class which contains a list of 8 neighbours, which itself is an object of type cell. Is it ok to do that. The code looks like this
class Cell {
private:
int position_row_;
int position_colm_;
std::shared_ptr<State> state_;
std::vector<Cell> neighbours_;
};
Now, the other question that is bugging me is, what type of relationship is it. While designing i thought of it to be 'Aggregation'; but now i don't think so.
Can someone please clarify?
A class cannot include itself as a data member class C { C c; }; for two reasons:
When you try to define the data member the class is still an incomplete type.
You are creating an endless chain of objects which would require infinite memory.
A class can contain a vector of itself class C { std::vector<C> vec; }; because, like a pointer, a vector declaration only requires that data type has been declared - not defined.
Your code will compile and run but you said your intent was for aggregation which isn't the case:
Your code std::vector<Cell> neighbours; is a case of composition because the objects in the vector are owned by the Cell object.
Using pointers to other Cell objects std::vector<Cell*> neighbours; would be a case of aggregation because the Cell object would use the objects in the vector but not own them.
std::vector<Cell> neighbours;
You are storing copy of neighbours. What if state of any neighbour changes? Do you need that change to be reflected into the vector? If yes, better store the pointers to the neighbours:
std::vector<std::shared_ptr<Cell>> neighbours;
This is considered to be Reflexive Association. Because it is satisfying following conditions with having its own type has a member variable
The associated object (member) is otherwise unrelated to the object (class)
The associated object (member) can belong to more than one object (class) at a time
The associated object (member) does not have its existence managed by the object (class)
This can lead to a chain of associations
The associated object (member) may or may not know about the existence of the object (class)
So I've got a class that I'm generalizing into a base class. One of the member variables is a 2D array of a struct.
struct SomeType
{
...
}
and then in the class's header:
SomeType member_variable_ [SIZE_ONE][SIZE_TWO];
But, in my situation, SIZE_TWO needs to be set when the class is initialized because it's going to be different depending on what's using this. What's the best way to have a 2D struct array with a size that's not yet set as a member variable?
The simplest way to solve it is to not use C-style arrays at all, but to use std::vector. Or possibly an std::array of vectors:
std::array<std::vector<SomeType>, SIZE_ONE> member_variable_;
Now you can easily insert as many (or as few) SomeType objects as needed, and still use the array-indexing syntax:
member_variable_[some_index][some_other_index]
To set a fixed size at runtime for the "second" Dimension, you can do something like this in the constructor:
for (auto& v : member_variable_)
v = std::vector<SomeType>(the_runtime_size);
You could use a template:
template<unsigned SIZE_TWO>
class theClass
{
SomeType member_variable_ [SIZE_ONE][SIZE_TWO];
SIZE_TWO will be set when you instantiate the class.
theClass<5> tc; //member_variable_ [SIZE_ONE][5];
You could also use containers like std::vector or std::array.
This is my (maybe a little bit weird) thought, suppose I want to define a std::set object to contain some stuff for later use, but unfortunately I'm not sure which type will be passed to std::set<not-sure> as template arg, and this not-sure type will be determined through a string, like this:
class X {
public:
foo()
{
char not_sure_type[20];
scanf("%s", not_sure_type);
if (strcmp(not_sure_type, "int"))
// then std::set<int>
else if (// "char")
// then std::set<char>
}
private:
void * _set;
};
This way, I can determine that std::set<int> will be instantiated or not, right? But how can I tell _set that you should point to a std::set<int>? Without knowing that, either I cannot use static_cast to cast _set from void * to std::set<int>*, back and forth.
So can I save the std::set<int> just like an data member for later use?
Any idea is appreciated.
If you will know the the type of the set element at run-time (based on a say string), you could maybe store a pointer to an abstract type into the set (set), and then use an Abstract Factory in the constructor of the class that holds the std::set to instantiate the actual Concrete Types for the elements during run-time based on the provided string.
The problem is in using raw pointers here, since you will need to do the cleanup within the class that has std::set. Since you want to use std::set, make sure that your Concrete Type for the element is Comparable. Not sure if this is the right way to go though.. you said to throw in ideas...
sounds to me like you are considering using c++ as a weak type language, such as python. sure there could be workarounds like using some abstract base class etc. but the bottom line I think is that defining the type at run time is against the paradigm of c++..
i know how to create a stack of vectors or int ,etc. But i dont know how to create a stack of a multidimentional arrays t[n][n] . Whats the way to implement it?
this is my actual implementation which its not working.
char map[20][20];
stack<map> soluciones;
Edit:
I think due my english most of you didnt undestand my question. Imagine i got some kind of a Game map. I am saving each multidimentional array on the stack. Thats my objective saving the map on a stack
Edit 2: im using Visual Studio 2010 Windows form application
In your code example, you use map (the name of your variable) in place of where a type name must stand (in stack<map> template instantiation). However, it won't work, not even if you use the proper type name (in this case you'd have to use typedef, e.g. typedef char TwoDimCharArray[20][20] and then try std::stack<TwoDimCharArray>:
There is still the problem that arrays don't have a default constructor (which std::stack expects); therefore, std::stack cannot be made to directly contain arrays; you'd have to wrap the array inside a class or struct (which can have a default constructor), e.g.:
class TwoDimCharArray
{
public:
// omit if there's nothing to initialize in map, then the
// compiler-generated constructor will be used
TwoDimCharArray()
{
// ... initalize map values
}
// ... provide access methods to map
private:
char map[20][20];
};
std::stack<TwoDimCharArray> soluciones;
Or use Boost.Array or C++11 std::array stuff! If these are available, they are definitely the better and easier choice!
I guess you should define a proper class for the game map. Then the stack of game maps is not a problem.
class GameMap {
public:
...
private:
char map_[1000][1000];
};
Then it wont matter for the stack how you allocate and manage the map data. E.g.
typedef std::stack<GameMap> GameMapStack;
Ddefine a wrapper class for multidimentional arrays like this:
template <class T, int X, int Y>
class Wrapper
{
public:
T array[X][Y];
}
Then use stack<Wrapper<char, 20, 20> >
First create structure and then define an empty multidimensional char array. then close structure and after thar write push and pop operations.
Can I have, as a private member of a class, an array of function pointers? Something like,
class MyClass {
public: //public stuff
private:
void (*specficFunctions[16]) (void);
}
I specifically don't want to use functors or functionoids.
Yes, though you usually want to use a typedef to keep the syntax a bit more manageable:
class MyClass {
typedef void (*fptr)(void);
fptr SpecificFunctions[16];
};
Note, however, that these are pointers to global functions, not member functions.
There's nothing special about function pointers. The declaration syntax may be confusing (which can be mitigated with typedefs) but they're not really different from any other pointer. If you can make an array of pointers, you can make an array of function pointers. There's also nothing special about a private member of a class compared with any other type of variable. If you can make an array, you can make an array a private member of a class.
Yes. (You can always answer this kind of question by trying to compile such code.)