I am bamboozled by function pointers.
Here is an example code:
#include <iostream>
class test
{
inline
void output_plumber_1(int* const arg_out, const int* const arg_in)
{
*arg_out = -*arg_in;
}
inline
void input_plumber_1(int* const arg_out, const int* const arg_in)
{
*arg_out = 2 * (*arg_in);
}
inline
void member_func(void (test::*output_plumber)(int* const arg_out, const int* const arg_in),
void (test::*input_plumber)(int* const arg_out, const int* const arg_in),
int arg)
{
int arg_copy;
(*input_plumber)(&arg_copy, &arg);
arg_copy = arg_copy + 1;
int arg_out;
(*output_plumber)(&arg_out, &arg_copy);
std::cout << arg_out << std::endl;
}
public:
void execute(int arg)
{
void (test::*output_plumber)(int* const arg_out, const int* const arg_in) = &test::output_plumber_1;
void (test::*input_plumber)(int* const arg_out, const int* const arg_in) = &test::input_plumber_1;
member_func(output_plumber, input_plumber, arg);
}
};
int main()
{
test mytest;
mytest.execute(1);
return 0;
}
What is it supposed to do?
This is a rather lean example, but essentially I have a program with a class with a member function which operates on some input data. Before performing the operation, and after performing the operation, the data must be fed into a set of input and output "plumber" functions which modify the data in preparation for "the operation" to take place, and "do something to it to correct for the initial preparation" after "the operation has taken place".
This sort of thing has arisen in my program as I am working with algorithms which operate on pairs of data (x, y) which only work when x > y. (Bizarre? But that's how it is.)
What is the problem?
Presumably numerous, however the immediate compiler output is the following:
main.cpp: In member function ‘void test::member_func(void (test::*)(int*, const int*), void (test::*)(int*, const int*), int)’:
main.cpp:27:11: error: invalid use of unary ‘*’ on pointer to member
(*input_plumber)(&arg_copy, &arg);
^
main.cpp:32:11: error: invalid use of unary ‘*’ on pointer to member
(*output_plumber)(&arg_out, &arg_copy);
This:
void (test::*output_plumber)(int* const arg_out, const int* const arg_in)
is a pointer to a member function of test, which takes two arguments and returns void. A pointer to member just points to a given member variable or function, but doesn't make any sense outside of the context of a class. So you can't call one without an instance.
The two allowed syntaxes are:
(obj.*ptr)(args...)
(p_obj->*ptr)(args...)
depending on whether or not the instance is a pointer. So the correct syntax to call your pointers would be:
(this->*input_plumber)(&arg_copy, &arg);
(this->*output_plumber)(&arg_out, &arg_copy);
And the correct way to call your function would be:
test_obj.member_func(&test::output_plumber_1, // <-- pointer to member
&test::input_plumber_1, // <-- pointer to member
0);
void (test::*input_plumber)(int* const arg_out, const int* const arg_in),
Based on your question, it appears that you believe that the above declares a parameter that's a function pointer.
Well, the above is not a function pointer. It's a class method pointer. It's not the same thing as a function pointer.
You cannot invoke input plumber as if it was a function pointer:
(*input_plumber)(&arg_copy, &arg);
You can't do it because this is a not a function pointer. Did I mention that this is not a function pointer, but a class method pointer? Yes, I think I did.
To invoke a method pointer, presuming that this is what you want to do, you must find an instance of a class whose method you wish to invoke, via the method pointer.
Asusming that you want to invoke this's method:
(this->*input_plumber)(&arg_copy, &arg);
Now, if you had some other pointer to test, lying around, for example:
test *some_ptr_to_test;
You would invoke that object's method pointer similarly:
(test->*input_plumber)(&arg_copy, &arg);
Related
Today I found out that code like that works. That sounds really strange to me, because as far as I always knew you can't modify any of members from const member function. You actually can't do it directly, but you can call non-const member function. if you mark member function as const that means that this pointer passed to the function is pointing to const object, then how non-const member function is called in the example bellow?
#include <iostream>
class X
{
public:
void foo() const
{
ptr->bar();
}
void bar() {}
private:
X * ptr;
};
int main()
{
}
Your member variable is not X, but pointer to X. As long as foo does not modify the pointer, it can be const.
When you have a pointer member, then the pointer is const in a const method. You won't be allowed to change the address stored in the pointer. But you can change the pointee all you like.
It's the difference between
X* const cannot_change_pointer; //this is how top-level const applies to pointers
const X* cannot_change_pointee;
What's even more interesting is that const on a method has no effect whatsoever on reference members for the same reason (a const method would only prevent you making a reference refer to something else which can't be done with a reference anyway).
That's seems perfectly OK. The call to foo does not modify the ptr member. Hence, the constness of foo is respected.
my 2 cents
I have C++ code that when I compile it I get the following error message:
error: no matching function for call to ‘DataSourceScheme::initObject(const QString&, const QString&, QVector<ColumnScheme*>* const&)’
initObject(datasourcescheme.name_, datasourcescheme.cmd_, datasourcescheme.columns_);
note: no known conversion for argument 3 from ‘QVector<ColumnScheme*>* const’ to ‘const QVector<const ColumnScheme*>*
The C++ code:
DataSourceScheme::DataSourceScheme(const DataSourceScheme &datasourcescheme) {
initObject(datasourcescheme.name_, datasourcescheme.cmd_, datasourcescheme.columns_);
}
void DataSourceScheme::initObject(const QString &name, const QString &cmd, const QVector<const ColumnScheme*> *columns) {
name_ = name;
cmd_ = cmd;
columns_ = new QVector<ColumnScheme*>();
if (columns != NULL) {
for (const ColumnScheme *column : *columns) {
addColumn(*column);
}
}
}
Please help
Thanks!
Perhaps you need clarification on the usage of const. foo* const A declares an object of type foo and creates a constant pointer to that object. The object can be changed but not the pointer. const foo* creates a pointer to a constant object. The object foo is not modifiable.
You are trying to pass a constant pointer to a list of editable objects to a function which requires a pointer to a list of constant objects. Do you see where this leads to problems? The usage within the function does not match the criteria set at the creation of the objects being passed.
You can pass a normal pointer to a function requiring a constant pointer. This conversion is OK, i.e.
void func(foo* const param); // Function declaration
foo* A;
func(A); // Function call OK
Also,
void func(foo* const param); // Function declaration
foo* const A;
func(A); // Function call OK
You cannot pass a pointer to a constant object to a function requiring a normal pointer. This conversion is OK, i.e.
void func(foo* param); // Function declaration
const foo* A;
func(A); // Error
I will add a side note. The use of void func(foo* const param); is good practice IMHO to signify that the function func is not expected to delete, manage memory, or reassign the pointer. This is why many microsoft API calls use the const keyword. They merely use the object but in no way manage it.
I just started learning C++, switching from a JAVA environment.
When reading through some Boost examples I found the following two methods defined in a class:
const char* data() const
{
return data_;
}
char* data()
{
return data_;
}
There are two things that confuse me.
First is the reserved word const, which I think I understand here. The first const refers to the char* which means that I cannot change the value of the pointer. The second const tells me that calling the function will not make changes to the state of the object I am calling. Is that a correct interpretation?
Second point of confusion is why one would have two methods with the same name and signature. How does the compiler know which one I meant to call? How do I know whether I am allowed to change the data after calling data() without know which of the two I called?
The first function returns a pointer to constant data. The const at the end of the function signature indicates that the function will not modify and class data members.
The second function returns a pointer to mutable data. The caller can use the pointer to modify the class member variable.
Search the web and SO for "const correctness".
There are several ways to declare const within a variable with a pointer:
const char * // you can modify the pointer, not the item pointed to
char const * // you can modify the pointer, not the item pointed to
char * const // you can modify the item pointed to, not the pointer
const char const * // you cannot modify either
char const * const // you cannot modify either
const char * const // you cannot modify either
As for the question, these two method definitions are overloads, and which one is called depends on the context. For example, if the caller is also in a const method, and making the call on one of it's members (who is an instantiation of the class that has the data() methods), then the const char * data() const method will be called, and caller can only save the return value in a variable of type const char *. Here is an example:
class MyClass {
DataClass data_obj_; // has both 'data()' methods described in your question
...
void my_method () const { // within this const method, data_obj_ cannot be modified
const char * data = data_obj_.data(); // calls const method
...
Here is an example where you would need both.
class foo {
char* data_;
public:
const char* data() const
{
return data_;
}
char* data()
{
return data_;
}
};
const foo bar;
foo bar2;
bar->data(); // this uses the const version.
bar2->data(); // this uses the non-const version.
Because bar is a const object it would be an error to call data() non-const version.
Code goes first:
class A
{
public:
...
int *foo() const
{
return _px;
}
private:
int *_px;
}
The member function foo returns a non-const pointer to private member _px, which, I think, opens a door to modifying member _px, right?
Is foo a const member function? Should I add a const in front of the return type?
UPDATE
What a const-member-function should guarantee is that, it cannot change any data-member, right?
In my case, function foo doesn't open a door to modifying class As data-member _px, but a door to modifying what _px pointing to, So my question is, does this violate what a const-function should guarantee?
A const member function can only return a const pointer or reference to a member.
However, your example isn't returning a pointer to a member; it's returning a copy of a member that happens to be a pointer. That is allowed in a const member function (even if the pointer happens to point to another member).
This would not be allowed (note that it's now returning a reference):
int *& foo() const {return _px;}
but this would (returning a const reference):
int * const & foo() const {return _px;}
int *_px becomes int *const _px inside a const member function this implies that the pointer cannot be reseated but the data pointed to is still modifyable. Further your function returns a copy of the pointer so it does not matter anyways.
It does not open a door to modifying _px but rather what _px points to. It's up to you to decide whether you want to allow this or not.
For example, an iterator::operator-> would return a non-const pointer and const_iterator::operator-> would return a const pointer. Both methods can be const themselves.
Yes, for your case it can. However, it's generally advised to not to do this, because it allows changing constant objects:
void f(const A& a)
{
*(a.foo()) = 42; // damn!
}
Yes, for example see the std::streambuf pointers:
protected:
char* pbase() const;
char* pptr() const;
char* epptr() const;
http://en.cppreference.com/w/cpp/io/basic_streambuf/pptr
Today I found out that code like that works. That sounds really strange to me, because as far as I always knew you can't modify any of members from const member function. You actually can't do it directly, but you can call non-const member function. if you mark member function as const that means that this pointer passed to the function is pointing to const object, then how non-const member function is called in the example bellow?
#include <iostream>
class X
{
public:
void foo() const
{
ptr->bar();
}
void bar() {}
private:
X * ptr;
};
int main()
{
}
Your member variable is not X, but pointer to X. As long as foo does not modify the pointer, it can be const.
When you have a pointer member, then the pointer is const in a const method. You won't be allowed to change the address stored in the pointer. But you can change the pointee all you like.
It's the difference between
X* const cannot_change_pointer; //this is how top-level const applies to pointers
const X* cannot_change_pointee;
What's even more interesting is that const on a method has no effect whatsoever on reference members for the same reason (a const method would only prevent you making a reference refer to something else which can't be done with a reference anyway).
That's seems perfectly OK. The call to foo does not modify the ptr member. Hence, the constness of foo is respected.
my 2 cents