set default parameter to a member variable [duplicate] - c++

This question already has answers here:
How to use a member variable as a default argument in C++?
(4 answers)
Closed 1 year ago.
I tried to set a default parameter to a member variable, it gave me this bug.
[cquery] invalid use of non-static data member 'num'
code
#include <iostream>
class Test{
private:
int val = 0;
public:
void print_num(int num = val){
std::cout << num << '\n';
}
}
int main(){
Test test;
test.print_num();
return 0;
}

Despite it being quite obvious what this would mean, you just can’t. The usual workaround is to provide an overload that (implicitly) uses this to get the member value.

In order to set a default value for a function parameter to a class member, the member must be static.
Citing the documentation,
Non-static class members are not allowed in default arguments
However, given the context of your code sample I doubt this is what you want to do (as every instance of Test class will point to the same val. Citing the docs:
Static members of a class are not associated with the objects of the class: they are independent variables
If you make val static in your example, and have multiple instances of Test in use by your code, you can (and very likely will) have some unexpected behavior. Consider:
#include <iostream>
class Test{
private:
static int val;
public:
void print_num(int num = val){
std::cout << num << '\n';
}
void set_val(int num) {
val = num;
}
}
int Test::val = 0;
int main(){
Test test1;
test1.set_val(1);
Test test2;
test2.set_val(2);
test1.print_num(); // results in "2"
return 0;
}
A better alternative would be to pass a pointer to your function like this:
#include <iostream>
class Test{
private:
int val = 0;
public:
void print_num(int* numptr = nullptr){
int num = (numptr ? *numptr : val);
std::cout << num << '\n';
}
}
int main(){
Test test;
test.print_num();
return 0;
}
Or, as described by Davis Herring, use an overload:
#include <iostream>
class Test{
private:
int val = 0;
public:
void print_num(int num){
std::cout << num << '\n';
}
void print_num() {
return print_num(val); // return is irrelevant here, but my preferred coding style
}
}
int main(){
Test test;
test.print_num();
return 0;
}
Edited to reflect the comment and example.

Your function definition doesn't actually know what val is because it doesn't actually live inside of your class. The compiler is actually making a function that contains your class as a parameter and abstracts away all of that. You'll want to set num to val within the function body.

Related

Initialization of member variable via parentheses doesn't work [duplicate]

This question already has an answer here:
Why class data members can't be initialized by direct initialization syntax?
(1 answer)
Closed 11 months ago.
For the following codes, can anyone explain why we can't initialize the variable data by parentheses?
#include <iostream>
using namespace std;
class X
{
private:
int data(1); // wrong here
public:
void print()
{
cout << data << endl;
}
};
int main()
{
X temp;
temp.print();
return 0;
}
There isnt actually much to explain, its just not valid syntax. Default member initializers are
class X
{
private:
int data{1}; // ok
int data2 = 42; // also ok
public:
void print()
{
cout << data << endl;
}
};
While int data(1); is not valid syntax for a default member initializer. See here for details: https://en.cppreference.com/w/cpp/language/data_members

Class non-static method pointer to global function

I'm trying to point a class method to a global function, i've seen this
but how i can't do it without instance?.
Consider this:
class x
{
public:
int(x::*GetVal)(int);
};
int RtX(int a)
{
return a * 4;
}
// declaration
int(x::*GetVal)(int) = (int(x::*)(int))&::Rtx; // :: global? // error
int main()
{
x a;
cout << (a.*GetVal)(4) << endl;
}
This returns me the error:
[Error] invalid cast from type 'int ()(int)' to type 'int
(x::)(int)'
x::GetX is a pointer to member. These are deeply complicated beasts, and you can't get them to point to non-member functions. The following code will work:
#include <iostream>
int RtX(int a) // Global non-member function
{
return a * 4;
}
class x
{
public:
int(x::*GetVal)(int);
// This is an instance member function which acts as a proxy and calls the
// the global function
int RtX(int a) { return ::RtX(a); }
};
int main()
{
x a;
a.GetVal =&x.RtX; // Assign the member variable. Could do this in the
// constructor. **NOTE** No casts!
std::cout << (a.*GetVal)(4) << std::endl;
}
If you find yourself reaching for a cast when dealing with function pointers and pointers-to-member-functions, stop - you are almost certainly doing it wrong, and while it will compile, it is very likely not to run properly.
Alternatively, as noted in the comments, use std::function.
#include <iostream>
#include <functional>
int RtX(int a)
{
return a * 4;
}
class x
{
public:
std::function<int(int)> GetVal;
// Initialize GetVal in the constructor.
x() : GetVal(RtX)
{}
// Alternatively, you can initialize the variable in with a default
// initialization. You can also declare the member const if you don't want to
// change it later.
const std::function<int(int)> gv = RtX;
/*
};
int main()
{
x a;
std::cout << a.GetVal(4) << std::endl;
}
Non static member functions need an instance in order to be called. You might consider using a static function member instead and if you also use std::function, you might get a simple code to assign your member function without instance:
#include <iostream>
#include <functional>
int RtX(int a)
{
return a * 4;
}
class x
{
public:
static std::function<int(int)> GetVal;
};
std::function<int(int)> x::GetVal = RtX;
int main()
{
x a;
std::cout << (a.GetVal)(4) << std::endl;
}

C++: Changing Class Member Values From Functions

I apologize for posting such a basic question, but I cant find a decent answer as to why this doesn't work, and how to get it to work.
I have simplified my issue here:
#include <iostream>
using namespace std;
class A {
public:
int x;
};
void otherFunction() {
A A;
cout<<"X: "<<A.x<<endl;
}
int main(){
A A;
A.x = 5;
otherFunction();
return 0;
}
Do the class members become constant after constructing?
How do I expand the scope of changes done to the class?
Are structs limited in this way?
Thank you in advance for answers.
You are not getting the expected output because in otherFunction() you are creating a new object of type A for which you have not assigned a value before!
Read up on scope of a variable in C++ to learn more
Try running the code given below, you should get the output as 5.
#include <iostream>
using namespace std;
class A {
public:
int x;
};
void otherFunction(A a) {
cout << "X: " << a.x << endl;
}
int main(){
A a;
a.x = 5;
otherFunction(a);
return 0;
}
Alternatively you can do this, which is considered a good practice in OOP
class A{
private:
int x;
public:
void update(int newx){
x = newx;
}
int getX(){
return x;
}
};
int main(){
A a;
a.update(5);
cout << a.getX() << endl;
return 0;
}
It is doing what it is supposed to do.
You are creating a new object A inside the function otherFunction, this new object will be local to the function.
Print the the value of A.x after the call of function otherFunction in the main , you will see the the value of A.x has changed.
The variable A in main is not the same as the variable A in otherFunction, so they won't have the same value.
One way to give otherFunction access to the value of A in main is to pass it in as a parameter. For example:
void otherFunction(A p) {
cout<<"X: "<<p.x<<endl;
}
int main(){
A a;
a.x = 5;
otherFunction(a);
return 0;
}
I have changed the names of the variables to make it a bit more clear. a is in main, and a copy of a is passed into otherFunction. That copy is called p in otherFunction. Chnages that otherFunction makes to p will not cause any change to a.If you want to do that, you would need to pass by reference, which is probably a topic a bit further along than you are now.

Access a private data member? [duplicate]

This question already has answers here:
Can I access private members from outside the class without using friends?
(27 answers)
Closed 7 years ago.
Here's some code for example
class A {
int i;
}
void main()
{
A a;
}
Is there any possible (probably hackish) way to access a::i in main?
Edit:
a::i is supposed to stay private.
*reinterpret_cast<int*>(&a) = 666;
That should do the trick.
Now, technically you're causing UB by using a post reinterpret_cast variable when the types are different. But, i is guaranteed to be at the beginning of A because A is a POD.
This will absolutely not work if there are virtual functions and is not guaranteed to if you have custom constructors.
YOU SHOULD NOT EVER DO ANYTHING REMOTELY LIKE THIS!!
A very hackish way that I've used for unit testing is (WARNING: only use under adult supervision):
// In your unit test only
#define class struct
#define private public
Put this in a header file that's only used for unit testing!
EDIT: (thanks to #Peter) And only use this for quick and dirty testing - NEVER check this into a repository!
For sure this is not guaranteed to work, but it will probably work on most platforms:
#include <iostream>
class A {
int i;
public:
A (int j) : i(j) { ; }
};
int awfulGetI(A const& a);
int main()
{
A a(3);
int j = awfulGetI(a);
std::cout << "a.i=" << j << std::endl;
}
// Ugly code that may or may not work here:
struct AA {
int i;
};
int awfulGetI(A const& a)
{
struct AA const* p = reinterpret_cast<AA const*>(&a);
return p->i;
}
When creating classes, usually the point is to have the encapsulation that they provide (though, of course, you may need to retrieve or mutate the values therein). There is always the possibility of using the memory address as is demonstrated in a couple of answers here, but have you considered creating a public "getter" function in your class that simply returns the value of the variable (since the function itself has access)?
Ex.
class A {
// private:
int i = 7;
// default value used for illustration purposes.
// public:
public int getInt()
{
return i;
}
}
int main() {
A a;
int x = a.getInt(); // when called, getInt() should return 7 (in this case).
cout << x; // just to check.
return 0;
}

Class variable accessible to one function or a static variable in member function that is still object aware

A static variable in a member function is a class level variable, meaning that all class instances access the same variable.
class foo{
int doingSomething(){
static int count =0;
static int someValue=0
count++;
if(count%10 == 0){
someValue *= counter;
}
someValue += counter;
return someValue * 2;
}
}
I want a way to count the number of times count() was called in each instance of foo separately, i can do this :
class foo{
int count;
int someValue;
int doingSomething(){
count++;
if(count%10 == 0){
someValue *= counter;
}
someValue += counter;
return someValue * 2;
}
but my problem with this approach is that count and somevalue is only used and accessed in foo by doingSomething(), so there is no reason for it to be a member variable, since it opens the door to it modified and used by other class member function, and i want to prevent that.
is there a solution that i am missing ?
EDIT 1:
The idea is to count the number of time that doingSomething() was called in each instance of Foo, and this value will be used only by 'doingSomething()' to compute other values, which will be different for each instance.
Why?
doingSomething() compute a int someVariable the first time is called, then stores it for later use, this stored value is used by doingSomthing() 10 times with every call, every 11calls int someVariable is recalculates and this new value is used...process repeated indefinitely.
you can hide your counter in a base class
class base_foo
{
public:
void doSomething()
{
counter++;
//other fun stuff
}
private:
int counter;
};
class foo : base_foo
{
public:
foo()
{
doSomething();
}
// your other code
};
One way I could see you doing this is with a std::map. You could have a static std::map<class_name*, int> in the function and every time the function is called use operator[] with this and increment the int part.
class Foo
{
public:
void bar()
{
static std::map<Foo*, int> counter;
counter[this]++;
}
};
C++, like many other languages, doesn't have a way that multiple functions can share a variable without allowing all functions access (besides putting them into a class together, which you already know). There are some ways to approximate what you want, however.
Here's a simple fix:
class foo
{
public:
int count ()
{
static int count_ = 0;
return ++count_;
}
};
Now only foo::count can access it, and it does double duty: increments it, and returns it.
If you don't like that, here's a lengthier fix that matches the desired behavior:
class foo
{
private:
class Counter //hides all that counting stuff
{
public:
//ctor initializing count...
private: //it's all hidden! Only friends can access
friend int foo::returnCount () const;
friend void foo::updateCount ();
int count () const { return count_; }
void updateCount (){ ++count_; }
int count_;
};
public:
//and only these two functions are friends.
int returnCount () const { return myCounter_.count (); }
void doSomethingAndIncCount() { myCounter_.updateCount (); }
private:
static Counter myCounter_;
};
So keeping all the contents of Counter private means nobody can access... except the functions you picked out, and designated as friends of Counter.
That's an awful lot of mess to go to, though. I'd go with the first solution, or else not worry about those other member functions accessing count.
I don't think there are options in C++ to have method scope private field. Encapsulation rules are that class is the unit of encapsulation so you should know what to do and what not to do within your own class.
You can achieve similar effect by using separate functor:
#include <iostream>
using namespace std;
class Counter {
private:
int counter = 0;
public:
int operator () () {
return counter++;
}
};
class Test {
public:
Counter count;
};
int main() {
Test test;
test.count();
test.count();
std::cout << test.count();
return 0;
}
In this case counter is completely inaccessible from class Test.
Is this what you are trying to achieve:
#include <iostream>
#include <string>
using namespace std;
class Foo
{
private:
int counter;
public:
Foo() : counter(0) {};
void count()
{
counter++;
}
int getCounter()
{
return counter;
}
};
int main()
{
Foo foo1;
Foo foo2;
foo1.count(); foo1.count(); foo1.count();
cout << "You called count() from foo1 " << foo1.getCounter() << " times" << endl;
foo2.count();
cout << "You called count() from foo2 " << foo2.getCounter() << " times" << endl;
}