Vectors if are data of a class should be assigned as private member of that class.
The class should provide the methods to access the vector methods needed.
Now I have my class Snake which encapsulate a snake for the classic game.
typedef std::vector<Polygon4>::const_iterator const_iterator;
enum directions{UP, DOWN, RIGHT, LEFT, IN, OUT, FW, RW };
class Snake
{
private:
enum directions head_dir;
int cubes_taken;
float score;
struct_color snake_color;
V4 head_pos;
std::vector<Polygon4> p_list; //the vector
public:
Snake();
V4 get_head_pos();
Polygon4 create_cube(V4 point);
void initialize_snake();
void move(directions);
void set_head_dir(directions dir);
directions get_head_dir();
void sum_cubes_taken(int x);
int get_cube_taken();
void sum_score(float x);
float get_score();
void set_snake_color();
//vector manipulation functions
const_iterator p_list_begin() const {return p_list.begin();}
const_iterator p_list_end() const {return p_list.end();}
void add_IntToP_list(Polygon4 cube){p_list.push_back(cube);}
void clear_list(){p_list.clear();}
unsigned int get_list_size(){return p_list.size();}
};
I have an other class in my program, the graphic management:
class MyGLBox{
private:
std::vector<Polygon4> p_list;
public:
//do stuff...
//management vectors:
const_iterator p_list_begin() const {return p_list.begin();}
const_iterator p_list_end() const {return p_list.end();}
void add_IntToP_list(Polygon4 cube){p_list.push_back(cube););
void clear_list(){p_list.clear();}
unsigned int get_list_size(){return p_list.size();}
}
Now every frame in the game I need to copy the snake p_list into the MyGLbox p_list. If the vectors were public it would have been pretty easy:
myGLBox.p_list = snake.p_list;
now if they are private:
transfer_function(*MyGLBox box, *Snake snake){
const_iterator cube;
for(cube = snake->p_list_begin(); cube != snake->p_list_end(); cube++){
box->add_InTop_list(*cube);
}
}
is it right what I'm trying to do? Is there a better way to do it? To me the for cycle seems pretty inefficent
If you already have a function
void add_IntToP_list(Polygon4 cube){p_list.push_back(cube););
for adding a single element, you can add another overload for adding a range of elements
void add_IntToP_list(vector<Polygon4>::const_iterator first,
vector<Polygon4>::const_iterator last)
{ p_list.insert(p_list.end(), first, last); }
and then call that with the range you want to add, maybe
box->add_IntToP_list(snake->p_list_begin(), snake->p_list_end());
You could try using a friend function:
void transfer_function(MyGLBox * box, Snake * snake )
{
box->p_list = snake->p_list;
}
// in class MyGlBox
friend void transfer_function(MyGLBox *, Snake *);
// in class Snake
friend void transfer_function(MyGLBox *, Snake *);
But if you have multiple such scenarios, this can easily become unmanageable.
Alternatively, you could still expose the vector directly via a get member. E.g:
// in class MyGLBox
std::vector<Polygon4> & get_p_list( )
{
return p_list;
}
It's not necessarily always "bad" if you return the vector itself - since you expose a lot of the vector's functionality anyways, it's not like the user has been given unwanted control over the data.
It seems pretty clear that friendship violates the programming exercise. I think your method is correct in that it provides the accessors to the private vector, and I agree, it is inefficient copying all that data. One optimisation you can do is to extend the vector:
v.reserve(v.size() + distance(v_prime.begin(),v_prime.end()));
v.insert(v.end(),v_prime.begin(),v_prime.end());
I robbed the code from here.
You have many ways to do it. One way is to friend your other functions so it can access your vector like a public variable.
Another is to make the variable itself public. Some may argue it's not good practice etc, but that's ridiculous. Are you trying to "protect" the vector from yourself?! Is that how confident you are in your own programming? To me, making private is only good for when you are writing a library for others to use not in your own program.
And finally, a remark on what you said. The for loop you presented is not at all inefficient. It is less efficient than using =, true, but adding one by one is also not that bad. vector's amortized performance is O(1). In fact if inserting something was intended to have cost 1, adding in vector has amortized cost 2.
Related
This is in relation to an earlier question I had. I haven't managed to solve the problem there but for now I'm just trying to get better acquainted with the code to figure out how to deal with that problem.
Towards that goal, I've got around to trying out the suggestions given in that question and I'm a little stumped as to why the following isn't working.
in the header I have
class A {
public:
typedef std::multimap<int, double> intdoublemap_t;
const intdoublemap_t& getMap() const;
void setkey(int k);
void setvalue(double v);
void insertIntoMap();
intdoublemap_t mMapA;
private:
int key;
double value;
};
class B {
public:
typedef std::multimap<int, double> intdoublemap_t;
void mapValues(const A& a);
private:
intdoublemap_t mMapB;
};
in the implementation I have
const A::intdoublemap_t& A::getMap() const { return mMapA; }
void A::setkey(int k) { key = k; }
void A::setvalue(double v) { value = v; }
void A::insertIntoMap(){mMapA.insert(std::make_pair(key, value));}
void B::mapValues(const A & a){ const A::intdoublemap_t& mref = a.getMap();
mMapB = mref; }
and in main()
A a;
a.setkey(10);
a.setvalue(1232.2);
a.insertIntoMap();
B b;
b.mapValues(a);
The code compiles fine and everything to do with a works as expected but the map is not passing to b at all. It stays empty
Can anyone tell me why?
edit: I took another look at this and saw how to do it. I knew it was something stupidly basic. I just had to set mref in the function to a map in B and then could call a function to work on that map within B.
As #FrancoisAndrieux notes, your getMap() only sets a reference local to the function - not the class' intdoublemap_t mref. If you want the latter to be a reference to a map elsewhere, you have three options:
Make it intdoublemap_t& mref, initialize it on construction of the B instance.
Make it std::reference_wrapper<intdoublemap_t> mref, set it whenever you want (e.g. in mapValues().
Make it intdoublemap_t* (or std::shared_ptr<intdoublemap_t> in both A and B), set it whenever you like.
Note: As #FrancoisAndrieux says in a comment, with the second and third option (and without std::shared_ptr) you will have to be careful not to allow the reference to be used after the original object's lifetime has expired.
Having said all the above - I must also say that your design seems rather off to me. You should really not be doing any of these things and I'm 99% sure you're approaching your task the wrong way.
I am currently taking a coding class at university and they have VERY specific requirements for the homework assignments.
For this week we have a class called Npt that represents a Nobel Prize winner. This class contains, amongst other things, the Name, the year of the prize and the field of the winner.
Now we should make another class, Nobelpreise, that contains a container for instances of said Nobel prize winner class. We are supposed to sort the elements of that container by the year of the Nobel Prize.
I wasn't able to use the std::sort function with a custom comparator correctly. This is what my code roughly looks like:
class Nobelpreise
{
private:
int numb;
vector<Npt> xx;
public:
Nobelpreise(){numb=0;}
void add(Npt &n1){xx.push_back(n1);numb++;return;}
Npt get_nobel(int i) {return xx[i];}
vector<Npt> get_xx() {return xx;}
int get_numb(){return numb;}
~Nobelpreise(){}
bool mycomp(Npt N1, Npt N2) {return (N1.get_jverl()<N2.get_jverl());}
};
The method get_jverl() comes from the Npt class and just returns the year.
Now the sort function always gives back an error saying that:
sort(Npl.get_xx().begin(), Npl.get_xx().end(), Npl.mycomp)
requires two arguments. Shouldn’t they be provided by the sort function?
I have also tried to overload the < operator which does not seem to work either.
edit1: added end() and removed the () from Npl.mycomp
edit2: we are required to make the comparator function a member of the class
Make your method mycomp static, and write a method which does the sort job.
class Nobelpreise
{
private:
int numb;
vector<Npt> xx;
public:
Nobelpreise(){numb=0;}
~Nobelpreise(){}
vector<Npt>& get_xx() {return xx;}
static bool mycomp( const Npt &N1, const Npt &N2 ) { return N1.get_jverl() < N2.get_jverl(); }
//^^^^^^
void Sort() { std::sort( xx.begin(), xx.end(), &mycomp ); }
};
The method Npt::get_jverl has to be const
returntype get_jverl() const { return ...; }
If you do the sorting outside your class note that you have to return a reference to your vector in your method: vector<Npt>& get_xx() {return xx;}
sort(Npl.get_xx().begin(), Npl.get_xx().end(), &Nobelpreise::mycomp)
Firstly, we'll fix the error that you're fetching two instances of the list:
sort(Npl.get_xx().begin(), Npl.get_xx().end, Npl.mycomp());
Replace with
auto v = Npl.get_xx();
std::sort(v.begin(), v.end(), Npl.mycomp());
I've added () to v.end, too, as we want to call it. However, we don't mean to call Npl::mycomp() here - std::sort wants to receive a function, not the return value:
auto v = Npl.get_xx();
std::sort(v.begin(), v.end(), Npl::mycomp);
This still won't work, as Npl::mycomp is an instance method, and std::sort won't call it with an object pointer for this. As it's implementation doesn't use this, it can be made a static method. Better still, it doesn't use any of the private members, so can be made a free function, outside of any class:
// I've renamed this to say what it does
bool year_precedes(const Npt& a, const Npt& b) {
return a.get_jverl() < b.get_jverl();
}
class Nobelpreise; // make the full declaration available
// for the following to compile
// I've made this a nonmember, too, as it only uses public methods
vector<Npt> sorted_prizes(const Nobelpreise& p)
{
auto v = p.get_xx();
std::sort(v.begin(), v.end(), year_precedes);
return v;
}
That should be enough to help you on your way.
You didn't say which version of C++, but assuming C++11 here's a more modern approach (compared to the two answers that are already here). Your requirements don't mention needing the comparator for anything else, so rather than write a comparator, you can do this:
std::sort(Npl.get_xx().begin(), Npl.get_xx().end(), [](const Npt& lhs, const Npt& rhs) {
return lhs.get_jverl() < rhs.get_jverl()
});
You could put this code in the Sort method of the Nobelpreise class as Rabbid suggests.
Compared to the other approaches here, I'd argue it makes the code more readable as you can see inline what is being compared, instead of having to jump to a new function just to read one more line of code (assuming of course that function is not being used anywhere else). It also makes the code faster because you are passing a lambda rather than a function pointer, but you shouldn't necessarily worry about that at this stage.
I am currently creating a class that has to be derived from std:: vector. I realize its probably bad to do this but I'm required to. Now my question is how do you access the created vector in the member functions to basically make the class access itself like a regular vector of integers? For example I am looking for the equivalent of myVector.at(0) to return the first term in the vector. Also, the size of the vector should always be 6. Here is the code I have so far:
class aHistogram : public vector<int>
{
public:
aHistogram(); //default constructor for histogram class
void update(int face); //Function to update histogram
void display(int maxLengthOfLine); //Displays histogram to the scale of maxLengthOfLine using x's
void clear();//Function to clear histogram bin counts
int count(int face) const; // Function to return number of times a face has appeared
private:
int numx, m, j; //Variables used in functions
};
#endif
The function that requires the class to access itself is below, I know there is no vector called "myVector" but what I'm lost about is the equivalent syntax to be able to perform the operation.
void aHistogram::clear()
{
//Clears bin counts to 0
myVector.at(0) = 0;
myVector.at(1) = 0;
myVector.at(2) = 0;
myVector.at(3) = 0;
myVector.at(4) = 0;
myVector.at(5) = 0;
}
If the function in question isn't overridden in the derived class, you
can just call it:
void HistoGram::clear()
{
at( 0 ) = 0;
// ...
}
This is also true for operators, but you'll have to use (*this) as the
left hand operator:
void HistoGram::clear()
{
(*this)[0] = 0;
// ...
}
If the function or operator is overridden, you'll either have to
qualify the function name,
void HistoGram::clear()
{
std::vector<int>::at( 0 ) = 0;
// ...
}
or cast the this pointer to the base class type:
void HistoGram::clear()
{
(*static_cast<std::vector<int>*>( this ))[0] = 0;
// ...
}
But are you sure that you want public inheritance here? You state that
the size of the vector should always be 6. There's no way you can
guarantee that using public inheritance; at the least, you need private
inheritance, and then using declarations for the operations that you
want to support. (I've a couple of cases where I've needed restricted
std::vector like this, which I've implemented using private
inheritance. And sometimes forwarding functions, when for example
I've wanted to expose only the const version of the function.)
Also: there are very, very few cases where std::vector<>::at is
appropriate. Are you sure you don't want [], with the bounds checking
you get in most modern implementations.
Instead of deriving from std::vector, in this case contain one (as a data member).
The problem with deriving is that it's then possible to treat a Histogram instance as just a std::vector, doing things that invalidate assumptions about the values of added data members.
In more technical jargon, with class derivation you have no guaranteed class invariant above the one provided by std::vector.
As a general rule of thumb, think of data member before class inheritance.
Sometimes inheritance is the thing, even inheritance from standard library container classes (e.g., std::stack is designed for inheritance), but not in this case.
About this: the size of the vector should always be 6.
You probably want to forbid some functionality to the user of the class. For example
vector::push_back
vector::pop_back
vector::insert
are functionalities that can change the size of the vector.
You can achive this by making such functions private members in the child class:
class aHistogram : public vector<int>
{
public:
aHistogram(){};
private:
vector<int>::push_back;
vector<int>::pop_back;
vector<int>::insert;
int numx, m, j;
};
Consider the following class member:
std::vector<sim_mob::Lane *> IncomingLanes_;
the above container shall store the pointer to some if my Lane objects. I don't want the subroutins using this variable as argument, to be able to modify Lane objects.
At the same time, I don't know where to put 'const' keyword that does not stop me from populating the container.
could you please help me with this?
thank you and regards
vahid
Edit:
Based on the answers i got so far(Many Thanks to them all) Suppose this sample:
#include <vector>
#include<iostream>
using namespace std;
class Lane
{
private:
int a;
public:
Lane(int h):a(h){}
void setA(int a_)
{
a=a_;
}
void printLane()
{
std::cout << a << std::endl;
}
};
class B
{
public:
vector< Lane const *> IncomingLanes;
void addLane(Lane *l)
{
IncomingLanes.push_back(l);
}
};
int main()
{
Lane l1(1);
Lane l2(2);
B b;
b.addLane(&l1);
b.addLane(&l2);
b.IncomingLanes.at(1)->printLane();
b.IncomingLanes.at(1)->setA(12);
return 1;
}
What I meant was:
b.IncomingLanes.at(1)->printLane()
should work on IncomingLanes with no problem AND
b.IncomingLanes.at(1)->setA(12)
should not be allowed.(In th above example none of the two mentioned methods work!)
Beside solving the problem, I am loking for good programming practice also. So if you think there is a solution to the above problem but in a bad way, plase let us all know.
Thaks agian
A detour first: Use a smart pointer such shared_ptr and not raw pointers within your container. This would make your life a lot easy down the line.
Typically, what you are looking for is called design-const i.e. functions which do not modify their arguments. This, you achieve, by passing arguments via const-reference. Also, if it is a member function make the function const (i.e. this becomes const within the scope of this function and thus you cannot use this to write to the members).
Without knowing more about your class it would be difficult to advise you to use a container of const-references to lanes. That would make inserting lane objects difficult -- a one-time affair, possible only via initializer lists in the ctor(s).
A few must reads:
The whole of FAQ 18
Sutter on const-correctness
Edit: code sample:
#include <vector>
#include <iostream>
//using namespace std; I'd rather type the 5 characters
// This is almost redundant under the current circumstance
#include <vector>
#include <iostream>
#include <memory>
//using namespace std; I'd rather type the 5 characters
// This is almost redundant under the current circumstance
class Lane
{
private:
int a;
public:
Lane(int h):a(h){}
void setA(int a_) // do you need this?
{
a=a_;
}
void printLane() const // design-const
{
std::cout << a << std::endl;
}
};
class B
{
// be consistent with namespace qualification
std::vector< Lane const * > IncomingLanes; // don't expose impl. details
public:
void addLane(Lane const& l) // who's responsible for freeing `l'?
{
IncomingLanes.push_back(&l); // would change
}
void printLane(size_t index) const
{
#ifdef _DEBUG
IncomingLanes.at( index )->printLane();
#else
IncomingLanes[ index ]->printLane();
#endif
}
};
int main()
{
Lane l1(1);
Lane l2(2);
B b;
b.addLane(l1);
b.addLane(l2);
//b.IncomingLanes.at(1)->printLane(); // this is bad
//b.IncomingLanes.at(1)->setA(12); // this is bad
b.printLane(1);
return 1;
}
Also, as Matthieu M. suggested:
shared ownership is more complicated because it becomes difficult to
tell who really owns the object and when it will be released (and
that's on top of the performance overhead). So unique_ptr should be
the default choice, and shared_ptr a last resort.
Note that unique_ptrs may require you to move them using std::move. I am updating the example to use pointer to const Lane (a simpler interface to get started with).
You can do it this way:
std::vector<const sim_mob::Lane *> IncomingLanes_;
Or this way:
std::vector<sim_mob::Lane const *> IncomingLanes_;
In C/C++, const typename * and typename const * are identical in meaning.
Updated to address updated question:
If really all you need to do is
b.IncomingLanes.at(1)->printLane()
then you just have to declare printLane like this:
void printLane() const // Tell compiler that printLane doesn't change this
{
std::cout << a << std::endl;
}
I suspect that you want the object to be able to modify the elements (i.e., you don't want the elements to truly be const). Instead, you want nonmember functions to only get read-only access to the std::vector (i.e., you want to prohibit changes from outside the object).
As such, I wouldn't put const anywhere on IncomingLanes_. Instead, I would expose IncomingLanes_ as a pair of std::vector<sim_mob::Lane *>::const_iterators (through methods called something like GetIncomingLanesBegin() and GetIncomingLanesEnd()).
you may declare it like:
std::vector<const sim_mob::Lane *> IncomingLanes_;
you will be able to add, or remove item from array, but you want be able to change item see bellow
IncomingLanes_.push_back(someLine); // Ok
IncomingLanes_[0] = someLine; //error
IncomingLanes_[0]->some_meber = someting; //error
IncomingLanes_.erase(IncomingLanes_.end()); //OK
IncomingLanes_[0]->nonConstMethod(); //error
If you don't want other routines to modify IncomingLanes, but you do want to be able to modify it yourself, just use const in the function declarations that you call.
Or if you don't have control over the functions, when they're external, don't give them access to IncomingLanes directly. Make IncomingLanes private and provide a const getter for it.
I don't think what you want is possible without making the pointers stored in the vector const as well.
const std::vector<sim_mob::Lane*> // means the vector is const, not the pointer within it
std::vector<const sim_mob::Lane*> // means no one can modify the data pointed at.
At best, the second version does what you want but you will have this construct throughout your code where ever you do want to modify the data:
const_cast<sim_mob::Lane*>(theVector[i])->non_const_method();
Have you considered a different class hierarchy where sim_mob::Lane's public interface is const and sim_mob::Really_Lane contains the non-const interfaces. Then users of the vector cannot be sure a "Lane" object is "real" without using dynamic_cast?
Before we get to const goodness, you should first use encapsulation.
Do not expose the vector to the external world, and it will become much easier.
A weak (*) encapsulation here is sufficient:
class B {
public:
std::vector<Lane> const& getIncomingLanes() const { return incomingLanes; }
void addLane(Lane l) { incomlingLanes.push_back(l); }
private:
std::vector<Lane> incomingLanes;
};
The above is simplissime, and yet achieves the goal:
clients of the class cannot modify the vector itself
clients of the class cannot modify the vector content (Lane instances)
and of course, the class can access the vector content fully and modify it at will.
Your new main routine becomes:
int main()
{
Lane l1(1);
Lane l2(2);
B b;
b.addLane(l1);
b.addLane(l2);
b.getIncomingLanes().at(1).printLane();
b.getIncomingLanes().at(1).setA(12); // expected-error\
// { passing ‘const Lane’ as ‘this’ argument of
// ‘void Lane::setA(int)’ discards qualifiers }
return 1;
}
(*) This is weak in the sense that even though the attribute itself is not exposed, because we give a reference to it to the external world in practice clients are not really shielded.
I am implementing a simple board game (Breakthrough) using OpenGL (plus GLUT and GLUI).
I'm thinking of implementing a Board class, which will have a vector<vector<Cell> > as one of its attributes. Cell represents a space in the game board. It can contain a GameObject. GameObject will be a pure abstract class. It mandates that its derivative classes implement render(), for example. Possible derivative classes will be:
Blank, representing an empty space
Pawn, representing a pawn (the only possible pieces in Breakthrough)
The board will be rendered by first rendering the board, then iterating through each Cell, getting its contents and calling render() for each of them.
The only possible way I can think of to achieving this is making the GameObject in Cell a pointer (board[y][x].getContents()->render(), where getContents() returns the GameObject*)
Is this the best way to do this? Is this an appropriate usage of pointers?
Let me promote my comment into an answer. This doesn't mean that it's in any sense complete, only that this allows me to spell out some code examples. My original comment:
That's OK, though you probably would do better with a std::unique_ptr<GameObject> or a std::shared_ptr<GameObject> so you don't get lost amids the manual lifetime management issues. Finally, how about a flat 1-D array accessible in strides?
Here's how I might go about this:
#include <vector>
#include <memory>
struct GameObject { virtual void render() const = 0; virtual ~GameObject() { } };
class Cell
{
std::unique_ptr<GameObject> m_go;
public:
void render() const { m_go->render(); }
Cell() : m_go(new BlankCell) { }
// more functions to reassign the cell value etc.
};
class Board
{
std::vector<Cell> m_board;
std::size_t m_length;
public:
Board(std::size_t length) : m_board(length * length), m_length(length) { }
Cell & cell(std::size_t i, std::size_t j) { return m_board(j + i * m_length); }
Cell const & cell(std::size_t i, std::size_t j) const { return const_cast<Board*>(this)->cell(i, j); }
// more...
}
Yes.
Also, maybe you should use another container for your cells (some kind of matrices or so)