How can I get the access to a private vector outside the class? I want to modify parameters of this objects.
I try to make getter and return the vector by reference, but when I try to change parameters of objects included in vector in main functions changes in vector are not saved.
class Restaurant
{
std::vector <Waiter> waiters_vector_;
public:
inline std::vector<Waiter> &GetWaitersVector() { return waiters_vector_; }
void Restaurant::AddWaiter(Waiter tmp)
{
waiters_vector_.push_back(tmp);
}
Restaurant();
~Restaurant();
};
class Waiter
{
int current_group_id_=0;
public:
int GetCurrentGroupId()
{
return current_group_id_;
}
void SetCurrentGroupId(int tmp)
{
current_group_id_ = tmp;
}
Waiter();
~Waiter();
};
int main()
{
Restaurant restaurant1;
Waiter w1, w2, w3;
restaurant1.AddWaiter(w1);
restaurant1.AddWaiter(w2);
restaurant1.AddWaiter(w3);
for (Waiter element : restaurant1.GetWaitersVector())
{
element.SetCurrentGroupId(123);
}
for (Waiter element : restaurant1.GetWaitersVector())
{
std::cout << element.GetCurrentGroupId() << std::endl;
}
}
result:
0
0
0
Both of your for loops are making copies
for (Waiter element : restaurant1.GetWaitersVector())
you want to modify references to the actual objects
for (Waiter& element : restaurant1.GetWaitersVector())
for (Waiter element : restaurant1.GetWaitersVector()) operates with a copy of the vector.
If you want to operate on the reference use
for (auto& element : restaurant1.GetWaitersVector())
// ^^^^^
instead.
But besides what's mentioned above, exposing your interned vector is a bad design idea. You should rather have a getter that does
inline const std::vector<Waiter> &GetWaitersVector() const { return waiters_vector_; }
and thus force clients accessing it to use specific functions of your class like AddWaiter() to modify it.
How can I get the access to a private vector outside the class? I want to modify parameters of this objects.
You don't. Or rather, you need to decide: Is the vector of waiters something private, or isn't it? Is it an implementation detail that code using this class should not be aware of? If not, do you really want to be able to manipulate it as-is on the outside? Or perhaps you want to use the PIMPL idiom to provide a .waiters() method which returns an obscure class, with methods such as add(...), `remove(...), etc.?
Those are design decisions for you to make.
Related
I am working with a large code base, and there are a number of publicly defined variables. Unfortunately, the functions of accessing these variables has changed, and this new functionality would be best encapsulated by public accessors and a private instance variable.
So, I am trying to make this change. To do so, I planned to make each public property private and then create accessors. But, I don't want to change any of the code which accesses the old public properties. For example:
After changing the public property to private, I have the following class:
class Test {
private:
int item = 5;
public:
int GetItem() {
return item;
};
void SetItem(int new_item) {
item = new_item;
};
};
In the past, "item" used to be a public property of the class, and it was accessed through:
Test* t = new Test();
int item = t->item;
Now though, I need to add new functionality to the way in which "item" is retrieved. For example:
int GetItem() {
// Some complicated code which changes "item"
return item;
};
How can I keep the same syntax:
int item = t->item;
But have this actually perform:
int item = t->GetItem();
Any help is greatly appreciated!
You can make int item = t.item; work, by defining item as a member variable whose type is a helper class with a custom conversion operator int() defined. Also, operator=(int new_value) to intercept the set operation.
What you can't make work is
int& item = t.item;
or
int* pitem = &t.item;
because both of these enable direct memory access, without going through any getter or setter. When creating the reference or pointer, you can't even determine how many accesses there will be or whether they will be reads or writes.
C++ is a compiled non-reflective language, i.e. you can't just "look names up as you access an element", because in the binary, there are no names anymore.
So, no, what you want is impossible. (at least not without restrictions – see Ben Voigt's excellent answer; having a "transparent" property which is in fact a getter call surely isn't worth the pitfalls you're building with that-)
Also, please don't let your C++ become Java just for the sake of having getters and setters – if they don't actually add security, I don't really see the point of using them
In case that your question is based in the fact that you don't want to call 2 different functions for setting and getting, you can make a function that returns a reference of the member:
int& Item()
{
// Some complicated code which changes *items
return item;
}
as you can see, the return type is int& instead of int. so you can use this function this way
t.Item() = someValue;
To expand on Ben Voight's answer, you can define a proxy template that allows this without the boiler plate:
template <typename Return, typename Containing, Return (Containing::* func)()>
struct proxy
{
Containing& c;
proxy(Containing& c) : c(c) {}
operator Return() { return (c.*func)(); }
Return& operator=(const Return& r) { return (c.*set)() = r; }
};
Then to define a "property"
class c {
int y_;
int get_y() { std::cout << "Getting y" << std::endl; return y_; }
public:
proxy<int, x, &x::get_y> y;
c() : y(*this) {}
};
And in client code
int main() {
c val;
val.y = 5;
std::cout << val.y << std::endl;
}
I think I have a design issue here and I would really appreciate your help.
I have a class Base representing a basic algorithm.
class BaseAlgo: public Algo<double>
{
public:
/// data structures
// ...
//
struct Item {
double profit;
double weight;
double xjSolution;
};
typedef std::pair<double, std::vector<Item>::iterator> ScaledItem;
protected:
std::vector<Item> & items_;
boost::ptr_vector<ScaledItem> largeItems_;
}
The BaseAlgo has some functions, some of them virtual, others not.
As a derived class I have
class DerivedAlgo: public BaseAlgo
{
public:
/// enhanced data structures
// ...
//
struct DerivedScaledItem : ScaledItem {
int additional;
};
}
In my virtual functions which I overload in DerivedAlgo, I need access to the additional parameter of DerivedScaledItem which is not quite the original intent of polymorphism. Is it somehow possible or do you propose a different design approach? I am open to anything at the moment as I am completely stuck.
Right now, the largeItems_ member ptr_vector in BaseAlgo holds ScaledItems (internally as pointers). I thought, I could use this somehow like this:
// in DerivedAlgo
void someMethod(std::vector<Item>::iterator someiterator){
DerivedScaledItem doubledItem = {};
doubledItem.first = 4.5;
doubledItem.second = someiterator;
doubledItem.additional= 2;
largeItems_.push_back(new UnboundedScaledItem(doubledItem));
boost::ptr_vector<DerivedScaledItem>::iterator it = largeItems_.begin();
std::cout << "added large item " << *it << std::endl;
}
When I cout the just added object, additional is set to 2. But after that, calling the getter for largeItems_, the additional field will be set back to 0, only the two fields which are known in ScaledItem are then set.
// in BaseAlgo
const boost::ptr_vector<ScaledItem>& getLargeItems() const
{
return largeItems_;
}
// from my test.cpp
DerivedAlgo obj;
// ... define someiterator
obj.someMethod(someiterator);
boost::ptr_vector<BaseAlgo::ScaledItem> largeItems = knapsack.getLargeItems();
boost::ptr_vector<DerivedAlgo::DerivedScaledItem>::iterator it = largeItems.begin();
std::cout << "read large item " << *it << std::endl;
I guess you didn't tell boost how to clone your ptr_vector-s elements, like described here:
http://www.boost.org/doc/libs/1_54_0/libs/ptr_container/doc/tutorial.html#cloneability
So in this line, where you create a copy of the vector (you could avoid this by declaring largeItems as a reference), they get copied via the constructor of ScaledItem, which looses your additional member.
boost::ptr_vector<BaseAlgo::ScaledItem> largeItems = knapsack.getLargeItems();
Regarding your question about another design:
You could pass the type of the vectors elements as a template parameter to the base class.
You could move the vector into the derived class, and provide only (virtual, abstract) functions to access single elements in the base class. If the base class shall also be able to create elements, you may need some kind of factory method. Because you don't want the base kind of elements in the vector.
I'm having some trouble refactoring a class that uses a std::vector of unique_ptrs. I currently have a class similar to:
class DataItemA
{
// various data members
};
class DataItemB
{
// various data members
};
class PointerOwner
{
public:
PointerOwner();
~PointerOwner();
void ComplexCalculationOnItemA()
{
for (auto itr = aItemsIOwn.begin(); itr != aItemsIOwn.end(); ++itr)
{
DataItemA& itemA= (**itr);
// complex calculations that also reference DataItemB items
}
}
// methods to add / remove items from the collections
private:
// This class owns the DataItems and control their lifetime.
// The objects cannot live outside of this instance.
std::vector<std::unique_ptr<DataItemA>> aItemsIOwn;
std::vector<std::unique_ptr<DataItemB>> bItemsIOwn;
};
I was refactoring the class to extract the complex calculation to another class and was unsure how to pass the vector of unique_ptrs to the other class and clearly 'state' that the calculation does not own the pointers. Is it reasonable to:
class ComplexItemAProcessor
{
ComplexItemAProcessor(const std::vector<std::unique_ptr<DataItemA>>& itemsToProcess)
{
// can I store the itemsToProcess in a member variable
}
SomeReturnType runCalcuation() {}
private:
// store the reference to calculation
}
Or is this better which can be done:
class ComplexItemAProcessor
{
ComplexItemAProcessor()
{
}
SomeReturnType runCalcuation(const std::vector<std::unique_ptr<DataItemA>>& itemsToProcess)
{
// process the collection as per original class
}
}
The lifetime of the ComplexItemAProcessor would be limited to scope of the original method.
class PointerOwner
{
public:
PointerOwner();
~PointerOwner();
ComplexCalculationOnItemA()
{
ComplexItemAProcessor processor; /** ? pass here **/
SomeReturnType result = processor.runCalcuation(/* ? pass here */);
}
private:
// This class owns the DataItems and control their lifetime.
// The objects cannot live outside of this instance.
std::vector<std::unique_ptr<DataItemA>> aItemsIOwn;
std::vector<std::unique_ptr<DataItemB>> bItemsIOwn;
};
Is either of these better than the other? Neither feels right to me, but that could be my limited experience with smart pointers in general. Is there another way for another class to process the vector without transferring ownership?
I don't think I need shared_ptrs as PointerOwner is the only owner.
I'm quite new to C++ and I am trying to store objects inside a std::vector like this:
Event.h:
//event.h
class Event
{
public:
Event();
Event(std::string name);
~Event();
void addVisitor(Visitor visitor);
private:
std::vector<Visitor> m_visitors;
};
Event.cpp:
//event.cpp
Event::Event() :
m_name("Unnamed Event")
{
}
Event::Event(std::string name) :
m_name(name)
{
}
void Event::addVisitor(Visitor visitor)
{
this->m_visitors.push_back(visitor);
}
void Event::listVisitors()
{
std::vector<Visitor>::iterator it;
for(it = this->m_visitors.begin();it != this->m_visitors.end(); ++it)
{
std::cout << it->getName() << std::endl;
}
}
Visitor.h:
//visitor.h
class Visitor
{
public:
Visitor();
Visitor(std::string name);
~Visitor();
std::string getName() const;
void listVisitors();
private:
std::string m_name;
};
Visitor.cpp:
//visitor.cpp
Visitor::Visitor() :
m_name("John Doe")
{
}
Visitor::Visitor(std::string name) :
m_name(name)
{
}
std::string Visitor::getName() const
{
return m_name;
}
main.cpp:
//main.cpp
int main()
{
Event *e1 = new Event("Whatever");
Visitor *v1 = new Visitor("Dummy1");
Visitor *v2 = new Visitor("Dummy2");
e1->addVisitor(*v1);
e1->addVisitor(*v2);
}
If I do it like this I would have to add a copy constructor which would make a deep copy so the object gets copied properly into the vector. I'm looking for a way around it by only storing pointers to the objects in a vector.
I already tried it with std::vector<std::unique_ptr<Visitor> > m_visitors, but then I got some errors when calling addVisitor in main.cpp. Of course I changed the declaration of the class members accordingly.
How would an appropriate declaration of the members and the member function look like to make it work?
Stylistically, if you are passing pointers, just accept pointers as the function arguments.
What's happening in the example code above is that the visitors are getting copied to become function arguments and the pointers you had are unreferenced by anything outside of the main function.
I can't speak to what the errors are that you're seeing as you didn't describe them but it probably has to do with incompatible types.
Just get rid of the news because for these data structures they're unnecessary.
int main()
{
Event e1("Whatever");
Visitor v1("Dummy1");
Visitor v2("Dummy2");
e1.addVisitor(v1);
e1.addVisitor(v2);
}
I would suggest that if you don't know how to use pointers you couldn't possibly want to store them instead (they're a hassle IMO to store in the vector when copying by value works just fine).
The compiler generated copy constructor should work just fine.
No manual deep copy required, because you are quite correctly using std::string, which supports RAII.
However, your main function has three memory leaks — there is no need to use new there anyway, so simply don't.
General rule of thumb:
If, at any time T, you're thinking of introducing more pointers into your code, then you're probably going in the wrong direction.
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.