passing a vector member variable by reference to another class method - c++

NOTE: I use pseudocode in my question
lets say i have a class called circle with an interface called
circle.h which
i also have a method called readdata but this is defined in another
class called rectangle(rectangle.h is the interface )
i want to call the method readdata in my circle class and pass in my
private member variable which is a vector. How can this be done? is it
correct to pass in a PRIVATE member variable by reference
to another class. Isn't this defeating the whole purpose of having
private member variables because now i am giving class rectangle
access to circle class vector variable since i pass it in by reference. Here is how i
do it(psuedocode)
circle.h
private:
vector<struct> vect;
public:
dataread()
circle.cpp
rectangle.h
readdata(vector &)
method dataread() //class method to fill up my struct
{
rectangle::readdata(vect); //i call rectangle readdata method but i
pass in a reference to my memebr variable....is this safe?
}
should i just declare the vector locally(in dataread method) and
assign it to the reference? any help would be greatly appreciated.
Right now it compiles but i have been told this is not good
programming practice

There is nothing wrong with passing references to private members to methods in other classes. For example:
void myClass::myMethod() {
std::copy(myVector1.begin(), myVector1.end(), myVector2.begin());
}
While that doesn't pass a reference to myVector1 directly, it does pass a writable iterator which is just about the same thing. The class is making a request for some object/function to do something with its data. So long as that other object/function only does what it is supposed to do, there's no problem.

I think I get what you are asking. Yes, you can pass a reference to your private data and No, you shouldn't do it. You can pass a const reference so that it can't be modified or pass a new vector with the contents copied. The best thing to figure out is why you need to do it that way, then figure out the best method for getting the data there.

Passing a pointer to a "private memory area" is not necessarily against the encapsulation idea because the object owning that memory area decides whom to allow access to. It doesn't allow "anyone to access it". On the other hand this doesn't look very natural.
You should return a pointer from the readdata method and use it in your circle instance.
At the same time doing this breaks a principle which I, personally, use: the one who allocates memory is responsible for it so it should also be the one frees it when appropriate. Taking this into consideration, it would probably be a good idea to return the actual vector and not a pointer to it (but this means copying a large amount of memory in case you're not using a compiler with "return value optimization").

Related

Question about keeping a reference to a unique_ptr in another class

Recently, I decided that it was time that I should dig into smart pointers. I read about the different kinds (unique, shared, weak), but I'm not sure about one thing.
Let say that I have a class Player and a GameMap class. The content of those classes are irrelevant for the next part. I also have an Engine class, that represents the object that will hold the main components of my game, like this:
class Engine {
public:
Engine();
~Engine();
private:
std::unique_ptr<Player> m_player;
std::unique_ptr>GameMap> m_gamemap;
};
These are the only instances of the player and game map that will be created, and the Engine owns them, and should be responsible for their allocation and deletion. So, a unique_ptr seems to be the good choice here.
Now, I would like to keep a simple reference to m_player in my GameMap class, since it would be easier for me than passing the m_player to each function that need it.
My question is: is using a raw pointer (obtained through the get() method) in the GameMap class the best way to keep a reference to the original unique_ptr located in the Engine class? I think that I can't use another unique_ptr pointing to the original one, since it would not be logical regarding to the use case of unique_ptr.
I think that using of raw pointer isn't the best way. For example, better way is use shared_ptr for player and gamemap. And adds weak_ptr of player into gamemap.

Getter for large member variables w/o copying

I have a class containing large member variables. In my case, the large member variable is a container of many objects and it must be private as I don't want to allow a user to modify it directly
class Example {
public:
std::vector<BigObject> get_very_big_object() const { return very_big_object; }
private:
std::vector<BigObject> very_big_object;
}
I want a user to be able to view the object without making a copy:
Example e();
auto very_big_object = e.get_very_big_object(); // Uh oh, made a copy
cout << very_big_object[11]; // Look at any element in the vector etc
I'm a bit confused about the best way to do it. I thought about returning a constant reference, i.e., make my getter:
const std::vector<BigObject>& get_very_big_object() const { return very_big_object; }
I read this article that suggests it could be risky and that that a smart pointer std::unique_ptr could be better, but that this problem can be best solved using modern C++11 move semantics. But I found that a bit cryptic.
What's the modern best practice for doing this?
I read this article that suggests it could be risky and that that a smart pointer std::unique_ptr could be better, but that this problem can be best solved using modern C++11 move semantics.
On this point, the article is flat-out wrong. A smart pointer does not remove the "risk".
Quick summary of relevant parts of the article
If a class returns a const reference to a data member, client code may introduce a const_cast and thereby change the data member without going through the class' API.
The article proposes (incorrectly) that the above can be avoided by using a smart pointer. The setup is for the class to maintain a shared pointer to the data, and have the getter return that pointer cast to a shared pointer to const data.
Critique of the points
First of all, this does not work. All one has to do is de-reference the smart pointer to get a const reference to the data, which can then be const_cast as before. Using the author's own example, instead of
std::string &evil = const_cast<std::string&>(obj.someStr());
use
std::string &evil = const_cast<std::string&>(*obj.str_ptr());
to get the same data-changing results when returning a smart pointer. The entire article is not wrong, but it does get several points wrong. This is one of them.
Second of all, this is not your concern. When you return a const reference, you are telling client code that this value is not to be changed. If the client code does so anyway, it's the client code that broke the agreement. Essentially, the client code invoked undefined behavior, so your class is free to do anything, even crash the program.
What's the modern best practice for doing this?
Simply return a const reference. (Most rules have exceptions, but in my experience, this one seems to be on target 95-99.9% of the time.)
What I did when I was working on my BDD-library for school is to create a wrapper class called VeryBigObject, which contacts the singleton upon instantiation and hides a reference-counting pointer, from there you can override the operator->() method to allow for direct access to the class's methods.
So something like this
class VeryBigObject {
private:
vector<BigObject>* obj;
public:
VeryBigObject() {
// find a way to instantiate with a pointer, not by copying
}
VeryBigObject(const VeryBigObject& o) {
// Update reference counts
obj = o.obj;
}
virtual VeryBigObject operator->(const VeryBigObject&); // I don't remember how to do this one, just google it.
... // Do other overloads as you see fit to mask working with the pointer directly.
};
This allows you to create a small portable class that you don't have to worry about copying, but also has access to the larger object easily. You'll still need to worry about things like caching and such though

c++ - raw pointer to shared_ptr

I'm using box2d and as you already may know, it holds a void* to an object which i can use as reference when collisions occur between different entities. Problem is that the original item is saved inside a shared_ptr since the ownership is unknown and different classes (example player class) can 'equip' another class (weapon).
I'm just wondering if its possible to put this pointer inside a shared_ptr and refer to the same object as the original one?
This is an example:
std::vector<std::shared_ptr<Environment>> listEnvironment;
listEnvironment.push_back(std::make_shared(new Weapon()));
//takes a void pointer
box2d->userId = listEnvironment.back().get();
//some shit happens somewhere else and collision occurs and I get pointer back from box2d's callback:
Environment* envPtr = static_cast<Environment*>(box2d->userId);
As you can see envPtr is going to cause trouble.
Is there a way to refer to the old smart-pointer and increase its reference value?
PS:
In actuality every class creates an box2d body which holds a 'this' pointer so i don't actually have the address to the smart-pointer either. The example above is kind narrowed down to give you a hint of the problem i'm facing.
Best regards
nilo
If Environment has std::enable_shared_from_this<Environment> as a parent class then, yes. Just call envPtr->shared_from_this().

Access member variables directly or pass as parameter?

I noticed that even when paying respect to the single responsibility principle of OOD, sometimes classes still grow large. Sometimes accessing member variables directly in methods feels like having global state, and a lot of stuff exists in the current scope. Just by looking at the method currently working in, it is not possible anymore to determine where invidiual variables accessible in the current scope come from.
When working together with a friend lately, I realized I write much more verbose code than him, because I pass member variables still as parameters into every single method.
Is this bad practice?
edit: example:
class AddNumbers {
public:
int a, b;
// ...
int addNumbers {
// I could have called this without arguments like this:
// return internalAlgorithmAddNumbers();
// because the data needed to compute the result is in members.
return internalAlgorithmAddNumbers(a,b);
}
private:
int internalAlgorithmAddNumbers(int sum1, int sum2) { return sum1+sum2; }
};
If a class has member variables, use them. If you want to pass parameters explicitly, make it a free function. Passing member variables around not only makes the code more verbose, it also violates people's expectations and makes the code hard to understand.
The entire purpose of a class is to create a set of functions with an implicitly passed shared state. If this isn't what you want to do, don't use a class.
Yes, definetely a bad practice.
Passing a member variable to a member function has no sense at all, from my point of view.
It has several disadvantages:
Decrease code readability
Cost in term of performances to copy the parameter on the stack
Eventually converting the method to a simple function, may have sense. In fact, from a performance point of view, call to non-member function are actually faster (doesn't need to dereference this pointer).
EDIT:
Answer to your comment. If the function can perform its job only using a few parameters passed explicitely, and doesn't need any internal state, than probably there is no reason to declare it has a member function. Use a simple C-style function call and pass the parameters to it.
I understand the problem, having had to maintain large classes in code I didn't originally author. In C++ we have the keyword const to help identify methods that don't change the state:
void methodA() const;
Use of this helps maintainability because we can see if a method may change the state of an object.
In other languages that don't have this concept I prefer to be clear about whether I'm changing the state of the instance variable by either having it passed in by reference or returning the change
this->mMemberVariable = this->someMethod();
Rather than
void someMethod()
{
this->mMemberVariable = 1; // change object state but do so in non transparent way
}
I have found over the years that this makes for easier to maintain code.

C++ Set object member as reference/pointer of member of a different object?

(I'm not sure if that title is worded correctly, as I'm still new to C++)
I have two classes, loosely represented here:
class SuperGroup
{
public:
LayoutObj theLayout;
}
class SomeClass
{
public:
LayoutObj myLayout;
SuperGroup myGroup;
}
During SomeClass's constructor, I want to set myGroup.theLayout to be pointing to SomeClass's searchLayout. Something like this:
SomeClass::SomeClass()
{
myGroup.theLayout = &myLayout;
}
Am I doing this correctly? Or do I need to be using a pointer? My code seems to compile okay, but when I execute it, it crashes, and I can tell its something to do with this assignment. Also, I'm not sure if its incorrectly coded, or if the SDK/API I'm using simply doesn't like it.
The reason I'm trying to reference myLayout with SuperGroup is because I have many methods in SuperGroup that need to use myLayout from SomeClass. I'm simply trying to avoid having the pass myLayout by reference into those methods every single time. Make sense? Is there an easier way to accomplish this?
You do indeed need a pointer. Try using:
LayoutObj *theLayout;
Without a pointer, you are trying to assign a LayoutObj to a memory address. This may compile, but is not the behavior you want. Instead, you need a pointer to point to the memory address of a LayoutObj.
The line myGroup.theLayout = &myLayout; remains the same.
As always is the case with C++, be careful that myLayout does not go out of scope before theLayout. If this happens, you have a dangling pointer. If there is any risk of this, consider using a smart pointer of some kind, or otherwise modify your design to accommodate this.
Yes, you would need to use a pointer: LayoutObj *theLayout;
In reference to your last paragraph, I would consider the some alternative designs, such as:
Requiring that the LayoutObj is passed into each method of SuperGroup, therefore decoupling the particular LayoutObj acted upon from the actions that can be performed, or
Moving those methods to SomeClass, if they're not needed elsewhere, or
Making them methods of LayoutObj itself.