I copied this program from a c++ practice book. What's going on behind the scenes?
The expected output is:
sum=30 sum=70
#include<iostream>
using namespace std;
class M
{
int x;
int y;
public:
void set_xy(int a, int b)
{
x=a;
y=b;
}
friend int sum(M m);
};
int sum (M m);
//so far so good, problem begins from here. what's happening after here?
{
int M ::*px = &M ::x;
int M ::*py = &M ::y;
M *pm =&m;
int s= m.*px+ pm->*py;
return s;
}
int main()
{
M n;
void (M :: *pf)(int, int) = &M ::set_xy;
(n.*pf)(10, 20);
cout <<"sum=" << sum(n) << endl;
M *op= &n;
(op-> *pf)(30,40);
cout << "sum=" << sum(n)<< endl;
cin.ignore();
getchar();
return 0;
}
The problem is because of extra whitespace at op-> *pf:
(op->*pf)(30,40); // ok
I think #fefe has probably said the reason in comment. ->* is a single operator, similar to .*. So, if those 2 are separated, then it will result in different syntax, which gives compiler error.
Take a look at Pointer to class data. And for the error, ->* is an operator, you can't put a space between them.
iammilind bet me to the error; op-> *pf must be changed so that you have ->* together as a single operator - a pointer to member operator (couldn't find a better link). The whitespace in op ->* pf is perfectly valid.
That's the same for something like i++; ++ is a single operator and will cause an error if you try and have i+ +.
Now for what it's doing. The example is of a pointer to a member function. pf is being declared as a member function of class M, that takes two int arguments with a void return type. It's being initialized to point to the M::set_xy function.
Inside main:
n is of type M, therefore in order to use pf to call set_xy of n you'd use the .* operator: (n.*pf)(10, 20);. That's equivalent to n.set_xy(10, 20);.
Since op is of type M* (a pointer to an M object), you'll need to use the ->* operator and call the function pointed to by pf as: (op->*pf)(30, 40);, which is equivalent to op->set_xy(30, 40);
Inside sum:
The examples are simply of pointers to member/instance variables, as opposed to member functions. It's simply demonstrating how you would add together m.x and m.y using those types of pointers.
Related
I've seen this used by other people and it looks really clever, but I'm not sure if it's good or bad practice. It works, and I like the way it works, personally, but is doing this actually useful in the scope of a larger program?
What they've done is dynamically allocate some data type inside the actual function argument, and delete it in the function. Here's an example:
#include <iostream>
class Foo {
private:
int number;
public:
Foo(int n) : number(n) { }
int num() { return number; }
Foo* new_num (int i) { number = i; }
};
void some_func (int thing, Foo* foo);
int main() {
std::cout << "Enter number: ";
int n;
std::cin >> n;
some_func(n, new Foo(0)); // <-- uses the 'new' operator with a function argument
return 0;
}
// calculates difference between 'thing' and 'n'
// then puts it inside the Foo object
void some_func (int thing, Foo* foo) {
std::cout << "Enter another number: ";
int n;
std::cin >> n;
std::cout << "Difference equals " << foo->new_num(thing - n)->num() << std::endl;
delete foo; // <-- the Foo object is deleted here
}
I knew that it was possible to use operators in function arguments, but I was only aware of doing this with the operators on levels 2, 4 through 15, and 17, as well as the assignment operators, ? :, ++ and --, unary + and -, !, ~, * and &, sizeof and casts. Stuff like this:
foo((x < 3)? 5 : 6, --y * 7);
bar(player->weapon().decr_durability().charge(0.1), &shield_layers);
So, I actually have two questions.
Is the new-as-an-argument good practice?
Since apparently any operator returning a type works if new works, are using these good practice?
::, new [], throw, sizeof..., typeid, noexcept, alignof
No, this is not clever at all. It takes a function that could be simpler and more general and reduces its capabilities for no reason, while at the same time creating an entry point into your program for difficult-to-debug bugs.
It's not clear to me exactly what Foo::new_num is meant to do (right now it doesn't compile), so I won't address your example directly, but consider the following two code samples:
void bad_function(int i, F * f)
{
f->doSomething(i);
delete f;
}
// ...
bad_function(0, new F(1, 2, 3));
versus
void good_function(int i, F & f)
{
f.doSomething(i);
}
// ...
good_function(0, F(1, 2, 3));
In both cases you allocate a new F object as part of the method call and it's destroyed once you're done using it, so you get no advantage by using bad_function instead of good function. However there's a bunch of stuff you can do with good_function that's not so easy to do with bad_function, e.g.
void multi_function(const std::vector<int> & v, F & f)
{
for(int i : v) { good_function(i, f); }
}
Using the good_function version means you're also prevented by the language itself from doing various things you don't want to do, e.g.
F * f; // never initialized
bad_function(0, f); // undefined behavior, resulting in a segfault if you're lucky
It's also just better software engineering, because it makes it a lot easier for people to guess what your function does from its signature. If I call a function whose purpose involves reading in a number from the console and doing arithmetic, I absolutely do not expect it to delete the arguments I pass in, and after I spent half an hour figuring out what's causing some obscure crash in some unrelated part of the code I'm going to be furious with whoever wrote that function.
By the way, assuming that F::doSomething doesn't alter the value of the current instance of F in any way, it should be declared const:
class F
{
void doSomething(int i) const;
// ...
};
and good_function should also take a const argument:
void good_function(int i, const F & f);
This lets anyone looking at the signature confidently deduce that the function won't do anything stupid like mess up the value of f that's passed into the function, because the compiler will prevent it. And that in turn lets them write code more quickly, because it means there's one less thing to worry about.
In fact if I see a function with a signature like bad_function's and there's not an obvious reason for it, then I'd immediately be worried that it's going to do something I don't want and I'd probably read the function before using it.
As a C++ learner, I came across the following piece of code from C++ Language Tutorial and got two questions, could any expert provide some guidance on those?
#include <iostream>
using namespace std;
int addition (int a, int b)
{ return (a+b); }
int subtraction (int a, int b)
{ return (a-b); }
int operation (int x, int y, int
(*functocall)(int,int))
{
int g;
g = (*functocall)(x,y);
return (g);
}
int main () {
int m,n;
int (*minus)(int,int) = subtraction;
m = operation (7, 5, addition);
n = operation (20, m, minus);
cout <<n;
return 0;
}
In function "operation" definition:
Question 1: for "g = (*functocall)(x,y)", does it deference the pointer that points to a function (ex.subtraction) and assign it to g?
Question 2: for "return(g)", I'm wondering why we put parenthesis for g?
And for "int (*minus)(int,int) = subtraction;" in the main function, is that okay if we write the following instead?
int (*minus)(int,int)
minus = subtraction
Question 1: for g = (*functocall)(x,y), does it deference the
pointer that points to a function (ex.subtraction) and assign it to g?
Answer: No.
(*functocall)(x,y);
is simply one allowable syntax for invoking the function from the pointer passed as a parameter. It is entirely equivalent to:
functocall(x,y);
Which simply eliminates the (*...) syntax which is allowable but unnecessary.
Question 2: for return(g), I'm wondering why we put parenthesis for
g?
The parenthesis too are discretionary and are superfluous to the return. Simply providing:
return g;
is all that is needed as there is no expression requiring evaluation priority provided by the enclosing (..).
Before I start, your code uses way more parenthesis than it needs.
Here is the same code, better formatted and reduced:
#include <iostream>
using namespace std;
int addition (int a, int b)
{ return a+b; }
int subtraction (int a, int b)
{ return a-b; }
int operation (int x, int y, int (*functocall)(int,int))
{
int g;
g = functocall(x,y);
return g;
}
int main () {
int m,n;
int (*minus)(int,int) = subtraction;
m = operation (7, 5, addition);
n = operation (20, m, minus);
cout <<n<<"\n";
return 0;
}
for "g = (*functocall)(x,y)", does it deference the pointer that points to a function (ex.subtraction) and assign it to g?
In a nutshell - yes. When calling a function through it's pointer, it is not necessary to explicitly dereference it. I know, it's surprising and counter to the way pointers are typically used.
Think of it this way. Whenever you are just writing the name of a function, you are essentially getting the function's pointer. This is why you wrote as you did, rather than write:
m = operation (7, 5, &addition);
You do not need to explicitly dereference when using a function pointer for the same reason you do not need to explicitly use the address of operator when taking its address in the first place.
Question 2: for "return(g)", I'm wondering why we put parenthesis for g?
There is positively no good reason to. In fact, there is no reason to do it for any of your return statements.
And for "int (*minus)(int,int) = subtraction;" in the main function,
is that okay if we write the following instead?
int (*minus)(int,int);
minus = subtraction;
Personally, I recommend you use:
int (*minus)(int,int) = nullptr;
minus = subtraction;
so as not to leave uninitialized variables, but otherwise, yes, absolutely. A pointer to function variable is just like any other variable.
I am a beginner in C++ and want to do simple example of composite function.
For example, in MATLAB, I can write
a = #(x) 2*x
b = #(y) 3*y
a(b(1))
Answer is 6
I searched following questions.
function composition in C++ / C++11 and
Function Composition in C++
But they are created using advanced features, such as templates, to which I am not much familiar at this time. Is there a simple and more direct way to achieve this? In above MATLAB code, user does not need to know implementation of function handles. User can just use proper syntax to get result. Is there such way in C++?
** Another Edit:**
In above code, I am putting a value at the end. However, if I want to pass the result to a third function, MATLAB can still consider it as a function. But, how to do this in C++?
For example, in addition to above code, consider this code:
c = #(p,q) a(p)* b(q) %This results a function
c(1,2)
answer=12
d = #(r) a(b(r))
d(1)
answer=6
function [ output1 ] = f1( arg1 )
val = 2.0;
output1 = feval(arg1,val)
end
f1(d)
answer = 12
In this code, c takes two functions as input and d is composite function. In the next example, function f1 takes a function as argument and use MATLAB builtin function feval to evaluate the function at val.
How can I achieve this in C++?
How about:
#include <iostream>
int main(int, char**)
{
auto a = [](int x) { return 2 * x; };
auto b = [](int y) { return 3 * y; };
for (int i = 0; i < 5; ++i)
std::cout << i << " -> " << a(b(i)) << std::endl;
return 0;
}
Perhaps I'm misunderstanding your question, but it sounds easy:
int a(const int x) { return x * 2; }
int b(const int y) { return y * 3; }
std::cout << a(b(1)) << std::endl;
Regarding your latest edit, you can make a function return a result of another function:
int fun1(const int c) { return a(c); }
std::cout << fun1(1) << std::endl;
Note that this returns a number, the result of calling a, not the function a itself. Sure, you can return a pointer to that function, but then the syntax would be different: you'd have to write something like fun1()(1), which is rather ugly and complicated.
C++'s evaluation strategy for function arguments is always "eager" and usually "by value". The short version of what that means is, a composed function call sequence such as
x = a(b(c(1)));
is exactly the same as
{
auto t0 = c(1);
auto t1 = b(t0);
x = a(t1);
}
(auto t0 means "give t0 whatever type is most appropriate"; it is a relatively new feature and may not work in your C++ compiler. The curly braces indicate that the temporary variables t0 and t1 are destroyed after the assignment to x.)
I bring this up because you keep talking about functions "taking functions as input". There are programming languages, such as R, where writing a(b(1)) would pass the expression b(1) to a, and only actually call b when a asked for the expression to be evaluated. I thought MATLAB was not like that, but I could be wrong. Regardless, C++ is definitely not like that. In C++, a(b(1)) first evaluates b(1) and then passes the result of that evaluation to a; a has no way of finding out that the result came from a call to b. The only case in C++ that is correctly described as "a function taking another function as input" would correspond to your example using feval.
Now: The most direct translation of the MATLAB code you've shown is
#include <stdio.h>
static double a(double x) { return 2*x; }
static double b(double y) { return 3*y; }
static double c(double p, double q) { return a(p) * b(q); }
static double d(double r) { return a(b(r)); }
static double f1(double (*arg1)(double))
{ return arg1(2.0); }
int main()
{
printf("%g\n", a(b(1))); // prints 6
printf("%g\n", c(1,2)); // prints 12
printf("%g\n", d(1)); // prints 6
printf("%g\n", f1(d)); // prints 12
printf("%g\n", f1(a)); // prints 4
return 0;
}
(C++ has no need for explicit syntax like feval, because the typed parameter declaration, double (*arg1)(double) tells the compiler that arg1(2.0) is valid. In older code you may see (*arg1)(2.0) but that's not required, and I think it makes the code less readable.)
(I have used printf in this code, instead of C++'s iostreams, partly because I personally think printf is much more ergonomic than iostreams, and partly because that makes this program also a valid C program with the same semantics. That may be useful, for instance, if the reason you are learning C++ is because you want to write MATLAB extensions, which, the last time I checked, was actually easier if you stuck to plain C.)
There are significant differences; for instance, the MATLAB functions accept vectors, whereas these C++ functions only take single values; if I'd wanted b to call c I would have had to swap them or write a "forward declaration" of c above b; and in C++, (with a few exceptions that you don't need to worry about right now,) all your code has to be inside one function or another. Learning these differences is part of learning C++, but you don't need to confuse yourself with templates and lambdas and classes and so on just yet. Stick to free functions with fixed type signatures at first.
Finally, I would be remiss if I didn't mention that in
static double c(double p, double q) { return a(p) * b(q); }
the calls to a and b might happen in either order. There is talk of changing this but it has not happened yet.
int a(const int x){return x * 2;}
int b(const int x){return x * 3;}
int fun1(const int x){return a(x);}
std::cout << fun1(1) << std::endl; //returns 2
This is basic compile-time composition. If you wanted runtime composition, things get a tad more involved.
I am reading C++ in easy steps and came across a piece of code for references and pointers that I do not understand.
The code is void (* fn) (int& a, int* b) = add;. As far as I know it does not affect the program itself but would like to know what this code does.
#include <iostream>
using namespace std;
void add (int& a, int* b)
{
cout << "Total: " << (a+ *b) << endl;
}
int main()
{
int num = 100, sum = 200;
int rNum = num;
int* ptr = #
void (* fn) (int& a, int* b) = add;
cout << "reference: " << rNum << endl;
cout << "pointer: " << *ptr << endl;
ptr = ∑
cout << "pointer now: " << *ptr << endl;
add(rNum, ptr);
return 0;
}
Use the spiral rule:
+----------------------+
| +--+ |
| ^ | |
void (* fn ) (int& a, int* b) = add;
^ | | |
| +-----+ |
+---------------------------+
fn is a pointer to a function taking two arguments (an int& named a and a int* named b) and returning void. The function pointer is copy initialized with the free function add.
So where in your code you have:
add(rNum, ptr);
That could be equivalently replaced by:
fn(rNum, ptr);
fn is a pointer to a function taking, from left to right, an int&, and an int*, that does not return anything.
You are assigning the function add to fn.
You could call the function add through the pointer, using exactly the same syntax as you would if you were use add.
One use of this technique is in the modelling of callback functions. For example, qsort requires a callback function for the sorting predicate. Function pointers are more common in C than in C++ where there are other techniques such as function objects, templates, lambdas, and even std::function.
If you read about the clockwise/spiral rule the declaration is easy to decipher:
You declare a variable fn, which is a pointer, to a function, taking some arguments and returning nothing.
Then you make this function-pointer fn point to the add function.
You can then use the function-pointer instead of calling add directly.
void (* fn) (int& a, int* b) = add; declares a function pointer named fn that points that points to a function that has a signature of void(int&,int*). it then intilizes the pointer to the add() function.
Such complicated declarations are easily read using the right-left rule, which works even when the clockwise spiral rule fails, which does even in case of something as simple as int* a[][10].
void (* fn) (int& a, int* b);
Start with the identifier fn and go from right to left, with the parenthesis flipping the direction. So fn is a pointer to a function taking are reference to int and a pointer to int and the function's return type is void.
It's called reading boustrophedonically :) See this answer for another example.
So I'm supposed to write a program that has num and denom as integer data members of the Fractions class. I'm also supposed to have member functions that can display an object's data values and an overloaded operator function for +. My program says my subscripted items are an invalid data type, but I don't know how to allow for the second fraction without them. Does anyone know how I can fix this?
My code is the following:
#include <iostream>
#include <cmath>
using namespace std;
int a, b, c;
class Fractions
{
private:
int num;
int denom;
public:
Fractions(int=1, int=1);
void operator!(void) const;
Fractions operator+(const Fractions&) const;
};
Fractions::Fractions(int n, int d)
{
if( d != 0)
num= n;
denom= d;
}
Fractions Fractions::operator+(const Fractions& f) const
{
a= num/denom;
b= num[1]/denom[1];
c= a + b;
c= (num * denom[1]+ denom * num[1])/(denom * denom[1]);
return c;
}
int main()
{
return 0;
}
You've declared num and denom as int but in your function you're treating them like arrays: b= num[1]/denom[1];
That won't work. What is it you want to do with this line b= num[1]/denom[1];? Is the idea to divide by the value of the fraction you're adding? If so maybe what you want is: b = f.num/f.denom;
My algebra isn't the best, but I can't recall using division when adding fractions, but that might be another question (or I might have it wrong).
The most immediate issue that is causing the error you're specifying is caused by trying to do:
b= num[1]/denom[1];
You initialized b, num and denom as an int, not an integer array. But you are trying to access an element of num and denom as if they were arrays.
Either initialize an array of integers for each or dropping the access operator for them will fix the error, but I don't believe it will give you your desired result.
The way you're overloading the '+' operator will not work. Since you have the '+' operator as a member, the object of that class becomes the left hand side of the operator, and what you are passing (const Fractions& f) becomes the right hand side.
You are not using the 'f" variable that you pass in at all, nor are you affecting that instance's members. All you are doing is changing some global variables that really aren't necessary. I recommend you read up on operator overloading since it seems you don't quite understand how it works.