C++ static object Class function - c++

Some code:
Please see the class myClass below . it has a constructor and a public recursive function find. Please see code:
#include <iostream>
using namespace std;
class myClass{
public:
myClass() {
//do stuff
}
int find(int i) {
static int j = 10;
if (i > 15)
return i;
j = j + 1;
return i * find(j + 1);
}
};
int main()
{
myClass mC1 ,mC2;
cout<< " 1.... return value = "<< mC1.find(10);
cout<< " \n 2... return value = "<< mC2.find(10);
return 1;
}
output:
1.... return value = 5241600
2.... return value = 170
The above progemn has a class myclass having a function find .. "find" function has a variabe . This is static which is required as i wanted a recursive function . Problem is static varible has life of a program & binded to class .
However I want the static to be object specfic and not class scope . I wanted both the function calls to return me same value .
Simply put , how to make a static varable in a class function , to be per object and not for whole class...

Do you need a member variable?
Hope the following code helps.
Best regards
Sam
class myClass{
public
myClass() {
m_j = 10;
}
private:
int m_j; // private member variable for find algorithm;
int find(int i) {
if(i>15)
return i;
m_j= m_j+1;
return i * find(m_j+1);
}
};

If you want a per object variable you need to make it a member of the respective object. There is no way to declare a variable inside a function to be specific to objects. The way you use use static member could be changed to be non-static anyway, i.e., you would get the necessary context: Make the function non-static and store the data in the object as needed.
That said, just because a function is recursive doesn't mean that it needs any sort of static context. Normally, all the necessary context is passed to the recursive function as parameters in which case the system keeps the necessary state on the stack. Since the stack is relatively limited in size you want to make sure that you don't need too much context in recursive functions with deep call stack.
Since you probably don't want to require the user to pass in some internal context, the find() function in the the interface would probably just delegate to the recursive function providing the necessary context. For example:
int find(int j, int i) {
if (15 < i) {
return i;
}
++j;
return i * find(j, j + 1);
}
int find(int value) {
return find(10, value);
}
(I'm not sure if I got the desired logic right because I didn't quite get what the function is meant to do...).

Related

How to erase a certain element from a shared_ptr to a vector of objects?

I have created a member variable (in the class Group) that is a shared_ptr to a vector (called members that stores objects of type User (a different class). Here is the member variable definition (empty):
std::shared_ptr <std::vector<User>> members = std::make_shared<std::vector<User>>();
To eliminate a certain User object from the vector (members), I created a member function (remove) inside the class Group. It checks all the User objects inside the vector and, when encounters the one with the a.URI value that is looking for, it erases the object at that location in the vector.
void Group::remove(User a) {
for (auto i = 0; i < members->size(); i++){
if (a.URI == (*(members->begin()+i)).URI) members->erase(*(members->begin() + i));
}
That is my remove function by now, but it doesn't work. I have checked different configurations but can`t make it work. Is there a problem with my function? How should this function be implemented (special rules for shared_ptr?)? Is there a better/optimal way?
I think no more code is needed here to solve my question. However, for those who want a MCV example, I tried to write one here (Ideone).
Firstly, std::vector::erase expects an iterator as its argument, so change
members->erase(*(members->begin() + i))
to
members->erase(members->begin() + i)
Secondly, after the element being erased, when i++ is evaluated, you will skip the next element or get out of the bound of the vector. You might change the loop to
for (auto i = 0; i < members->size(); ) {
if (a.URI == (*(members->begin()+i)).URI)
members->erase(members->begin() + i);
else
i++;
}
Why don't you declare the vector members as static member of the group class. I did it like this:
#include <bits/stdc++.h>
using namespace std;
class User{
public:
int URI;
User(int a){
URI = a;
}
};
class Group {
public:
static vector<User> members;
void remove(User a) {
for (int i = 0; i < members.size();){
if (a.URI == (*(members.begin()+i)).URI) members.erase((members.begin() + i));
else
i++;
}
}
Group(User a, User b, User c){
members.push_back(a);
members.push_back(b);
members.push_back(c);
}
};
vector<User> Group::members;
int main() {
User a(1), b(2), c(3);
Group obj(a, b, c);
obj.remove(a);
return 0;
}
Hope it helps.

Binding member function to a local static variable

Precondition:
Here is a function:
typedef std::function<void (int)> Handler;
void g(const Handler& h) {
h(100);
}
, and a class:
class A {
public:
void f0(int n) {
std::cout << m + n << std::endl;
}
void f1() {
::g(std::bind(&A::f0, this, std::placeholders::_1));
}
int m;
};
And this will print two lines, '101' and '102':
int main() {
A a1;
a1.m = 1;
a1.f1();
A a2;
a2.m = 2;
a2.f1();
return 0;
}
Now I realized A::f1() will be called very frequently,
so I modified it like this(new version):
void A::f1() {
static const Handler kHandler =
std::bind(&A::f0, this, std::placeholders::_1);
::g(kHandler);
}
My Questions:
Is it safe to bind this pointer to a local static variable?
Is there no functional difference between two versions?
Can I expect the new version will really gain some performance benefit?
(I suspect my compiler(MSVC) will optimize it by itself,
so I may not need to optimize it by myself).
EDITED ----------
I run the new version and realized that the result is not the same as the original one.
It prints two lines, '101' and '101' again(not '102').
Poor question, sorry for all.
EDITED 2 ----------
Please refer to my new question which I might truly intend:
Binding member function to a member variable
No, this is not safe (nor works as intended). The static variable is shared among all instances to A, and you bind this in this static function object kHandler when calling f1 for the first time. So the bound parameter is always equal to the instance on which you called f1 first, i.e. in your case a1.
It's basically the same with this function:
int f(int a) {
static int b = a;
return b;
}
Call this function multiple times, and you will always get the value of the first call. (Demo)
Alternatives:
You could, if you can live with a space overhead, use a member variable for the bound function, though. I guess implementing this is straight-forward.
A non-thread-safe alternative (I'd not recommend using this!) could be to store the "this" pointer in a static member variable ("that") and make f0 static and use "that" instead of "this":
class A {
static A * that = nullptr;
public:
static void f0(int n) {
assert(that);
std::cout << that->m + n << std::endl;
}
void f1() {
assert(!that);
that = this;
::g(&A::f0);
that = nullptr;
}
int m;
};
Raymond Chen's comment is Correct - by using static you're only ever creating one instance of kHandler, and if the instance of A associated with that first call ever dies, then the bound "this" pointer will be dead.
I recommend removing static:
void A::f1() {
const Handler kHandler =
std::bind(&A::f0, this, std::placeholders::_1);
::g(kHandler);
}
This is safe because kHandler will exist across the lifetime of the g call.

How can I access a class's member function via an array of pointers?

I have a pretty standard class with some public member functions and private variables.
My problem originally stems from not being able to dynamically name object instances of my class so I created an array of pointers of the class type:
static CShape* shapeDB[dbSize];
I have some prompts to get info for the fields to be passed to the constructor (this seems to work):
shapeDB[CShape::openSlot] = new CShape(iParam1,sParam1,sParam2);
openSlot increments properly so if I were to create another CShape object, it would have the next pointer pointing to it. This next bit of code doesn't work and crashes consistently:
cout << shapeDB[2]->getName() << " has a surface area of: " << shapeDB[2]->getSA() << shapeDB[2]->getUnits() << endl;
The array of pointers is declared globally outside of main and the get() functions are public within the class returning strings or integers. I'm not sure what I'm doing wrong but something relating to the pointer set up I'm sure. I'm writing this code to try and learn more about classes/pointers and have gotten seriously stumped as I can't find anyone else trying to do this.
I'm also curious as to what the CShape new instances get named..? if there is any other way to dynamically create object instances and track the names so as to be able to access them for member functions, I'm all ears.
I've tried all sorts of permutations of pointer referencing/de-referencing but most are unable to compile. I can post larger chunks or all of the code if anyone thinks that will help.
class CShape {
int dim[maxFaces];
int faces;
string units;
string type;
string name;
bool initialized;
int slot;
public:
static int openSlot;
CShape();
CShape(int, string, string); // faces, units, name
~CShape();
void initialize(void);
// external assist functions
int getA(void) {
return 0;
}
int getSA(void) {
int tempSA = 0;
// initialize if not
if(initialized == false) {
initialize();
}
// if initialized, calculate SA
if(initialized == true) {
for(int i = 0; i < faces; i++)
{
tempSA += dim[i];
}
return(tempSA);
}
return 0;
}
string getUnits(void) {
return(units);
}
string getName(void) {
return(name);
}
// friend functions
friend int printDetails(string);
};
// constructor with values
CShape::CShape(int f, string u, string n) {
initialized = false;
faces = f;
units = u;
name = n;
slot = openSlot;
openSlot++;
}
My guess is you use the CShape constructor to increment CShape::openSlot?
You're probably changing the value before it's read, thus the pointer is stored in a different location.
Try replacing openSlot with a fixed value to rule out this CShape::option.
-- code was added --
I'm pretty sure this is the problem, the constructor is executed before the asignment, which means the lhs. will be evaluated after CShape::openSlot is incremented.

Static member function pointer to hold non static member function

This has defeated me. I want to have a static class variable which is a pointer to a (non-static) member function. I've tried all sorts of ways, but with no luck (including using typedefs, which just seemed to give me a different set of errors). In the code below I have the static class function pointer funcptr, and I can call it successfully from outside the class, but not from within the member function CallFuncptr - which is what I want to do. Any suggestions?
#include <stdio.h>
class A
{
public:
static int (A::*funcptr)();
int Four() { return 4;};
int CallFuncptr() { return (this->*funcptr)(); }
// doesn't link - undefined reference to `A::funcptr'
};
int (A::*funcptr)() = &A::Four;
int main()
{
A fred;
printf("four? %d\n", (fred.*funcptr)()); // This works
printf("four? %d\n", fred.CallFuncptr()); // But this is the way I want to call it
}
Try this instead:
#include <iostream>
class A {
public:
typedef int (A::*AMemFn)();
static AMemFn funcptr;
int Four() { return 4; }
int CallFuncptr() { return (this->*funcptr)(); }
};
A::AMemFn A::funcptr = &A::Four;
int main()
{
A fred;
std::cout << "four? " << fred.CallFuncptr() << std::endl;
}
jweyrich has a nice looking work around (and I suggest you use it), but I thought I'd elaborate on what the real problem in the code is:
Your problem is this line:
int (A::*funcptr)() = &A::Four;
This is defining a global variable called funcptr that is of the right type, rather than A::funcptr.
What you need is this mess:
int (A::*(A::funcptr))() = &A::Four;
This ugly mess is why I suggest you go down the typedef path to get a nice looking version like jweyrich's solution.
A static variable is not a member of a particular object -- it can only be accessed through the classes namespace. CallFuncptr should be rewritten:
int CallFuncptr() { return (*funcptr)();
which I think should work, since this function can access functions in A's namespace without specifying it.
Also, function pointers are more of a C construct than C++. You can access the static variable outside the class with the code:
A::CallFuncptr
since CallFunctptr just resides in A's namespace

Working with objectives and calling methods?

I've probably become a bit to used to Java and am finding this harder than it should be. Heres what I have.
myObject[0] = new item1(this);
class item1
{
private:
int x;
int y;
public:
item1( passedPointer* pOne )
{
x = 5;
y = 5;
}
int returnX() { return x; }
int returnY() { return y; }
}
Then in another method I thought I could just say:
void check()
{
int y = item1.returnY();
int x = item1.returnX();
}
But I am getting the common error: a nonstatic member reference must be relative to a specific object.
There is only one instance of this class item1, what would be the best way to do this? This is just a simplified fragment of what I'm actually doing, not the actual code.
Item1 is a class. You have to create an instance of it before you can access its non-static members. Try looking here for some basic information.
void check(){
int y = item1.returnY;
int x = item1.returnX;
}
This would also be incorrect in Java, since neither returnX nor returnY are statics, you need an object on which to apply the operation, and you also need the parenthesis of the method call:
void check() {
item1 i;
int y = i.returnY();
int x = i.returnX();
}
Perhaps implementing the Singleton pattern would not do you harm, since you want only one instance of the object. You could declare the object as global or static to a function too, then get the values.
Then again, you could also declare the functions as static, and add another one to initialize the static values of the variables which need to be returned by those methods. There are a lot of solutions to this depending on your situation which can not be fully grasped by the short amount of code you have pasted.
You created an instance of class item1 with the line
myObject[0] = new item1(this);
Unlike JAVA, in C++ there are pointers and new returns a pointer to the object (so myObject[0] is a pointer to the instance) so you need the -> operator. To activate the method you should write:
myObject[0]->returnX();
If you wish to have only one instance than implement the class as a singleton.