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.
Related
I have two classes TestClass and OtherClass, where TestClass has a member variable of type OtherClass named m_otherClass. Note that this is not declared to be const.
In the minimal example provided below; when m_otherClass is a pointer, then everything compiles and runs fine. If I change this to be a non-pointer, then I get compiler errors (the changes are commented out in the minimal example):
"Non-const function 'setOtherMember' is called on const object"
error: passing 'const OtherClass' as 'this' argument discards qualifiers [-fpermissive] m_otherClass.setOtherMember();
#include <iostream>
#include <memory>
class OtherClass {
public:
void setOtherMember() {
m_otherMember = 2;
std::cout << "Other member is now 2" << std::endl;
}
private:
int m_otherMember = 0;
};
class TestClass {
public:
TestClass(): m_otherClass(std::make_unique<OtherClass>())
// TestClass()
{}
void myMethod() const {
m_otherClass->setOtherMember();
// m_otherClass.setOtherMember();
}
private:
std::unique_ptr<OtherClass> m_otherClass;
// OtherClass m_otherClass; // If changing to this I get the error!!
};
int main() {
TestClass testClass;
testClass.myMethod();
return 0;
}
Is this because myMethod() is const (and then promising not to change any member variables), whereas setOtherMember() is non-const and is changing OtherClass's member variable, and then indirectly also the m_otherClass object?
But why does this not fail then when m_otherClass is a pointer?
And why does the compiler error says that passing 'const OtherClass' as 'this'argument fails, when m_otherClass has not been declared to be const?
Const qualified member functions in most cases aren't allowed to change an object's members state. This means, that every member which is not mutable can not be modified in this function body. When dealing with pointers, you just say, that you won't modify a pointer value, not a pointee itself. It is because constness of a pointer is not propagated on its pointee.
In the upcoming standards it will be possible to change this behaviour by using propagate_const.
A simpler example to demonstrate the difference.
struct Foo { int m; };
const Foo f = {10};
f.m = 20; // Not allowed since modifying f.m modifies f.
struct Bar { int* p; };
int i = 10;
int j = 20;
const Bar b = {&i};
b.p = &j; // Not allowed since modifying b.p modifies b.
*(b.p) = j; // Allowed since it does not change b or b.p. It changes the value
// of what b.p points to.
When you put const on a method, all your data members are treated as being const. And that is why you get the error when you have OtherClass as a value, since it turns into a value of const OtherClass.
Now when you use a pointer of OtherClass you get const std::unique_ptr<OtherClass> and the const applies only to the pointer but not to the value it points to.
But why does this not fail then when m_otherClass is a pointer?
Because it is const correct to modify an object pointed by a const pointer, as long as it is a pointer to non-const such as in your case.
And why does the compiler error says that passing 'const OtherClass' as 'this'argument fails, when m_otherClass has not been declared to be const?
myMethod is declared const. Therefore this is a pointer to const. Therefore the lvalue this->m_otherClass is also const regardless of whether the object named by the lvalue is const or not.
In C++ Primer P259, it says
Objects that are const, and references or pointers to const objects,
may call only const member functions.
Based on my current understanding, however, pointers to const objects not necessarily applies because the pointer itself is nonconst. As long as the member function does not modify the object being pointed to, it's legal to call nonconst member functions on pointers to const objects.
Is it correct?
Edit: OK I get it now, it is because when we "call member function on the pointer", we are actually dereferencing it first, and use the object underneath.
The quote is correct.
Try this
class TestClass
{
public:
void nonconst(){};
void constMethod() const {}
};
int main()
{
TestClass const *s = new TestClass();
//s->nonconst(); // (1) no not legal
s->constMethod();
s = new TestClass(); // (2) yes legal
s->constMethod();
}
s is a pointer to a constant. Calling a non const method causes
passing ‘const TestClass’ as ‘this’ argument discards qualifiers [-fpermissive]
However s can point to a different instance. As said in the comments the pointer can be pointed to a different variable.
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);
I don't get the difference between passing the instance of an object to passing a dereferenced object. I have
class A
{
public:
A() {}
void m() {}
};
void method(A& a)
{
a.m();
}
int main(int argc,char** argv)
{
method(A());
return 0;
}
The call above does not work with compiler errors:
In function 'int main(int, char**)':
error:no matching function for call to 'method(A)'
note: candidates are:
note: void method(A&)
note: no known conversion for argument 1 from 'A' to 'A&'
note: void method(B&)
no known conversion for argument 1 from 'A' to 'B&'
But if I write
method(*(new A()));
it does.
Can anyone please tell my why and how to resolve the problem if I cannot change the method I want to call?
In the first case, you create a temporary object that you try to pass to method.
A temporary object cannot be modified (it doesn't make sense to modify it, it will be gone the moment method returns). So to pass a temporary by reference, you must pass by a const reference.
void method(const A& a)
{
}
Here you are creating a temporary object:
method(A()); // A() here is creating a temporary
// ie an un-named object
You can only get const& to temporary objects.
So you have two options:
Change the interface to take a const reference.
Pass a real object.
So:
// Option 1: Change the interface
void method(A const& a) // You can have a const
// reference to a temporary or
// a normal object.
// Options 2: Pass a real object
A a;
method(a); // a is an object.
// So you can have a reference to it.
// so it should work normally.
If this were legal, horrible things would happen. Consider:
void addOne(double& j) { ++j; }
int q = 10;
addOne(q);
This would create a temporary double, add one to it, and leave your original q unmodified. Ouch.
If method modifies its parameter, your code is broken. If it doesn't, it should take a const reference.
Problem that you see is that your function accepts only lvalue of type A. To solve the issue you can either change your function to accept type A by value:
void method( A a ) {}
or by const reference:
void method( const A &a ) {}
or by rvalue reference (if you use C++11):
void method( A &&a ) {}
or pass lvalue of type A to your method:
A a; method( a );
If you want to understand the problem deeper read about lvalue in c++
I have a class constructor that expects a reference to another class object to be passed in as an argument. I understand that references are preferable to pointers when no pointer arithmetic will be performed or when a null value will not exist.
This is the header declaration of the constructor:
class MixerLine {
private:
MIXERLINE _mixerLine;
public:
MixerLine(const MixerDevice& const parentMixer, DWORD destinationIndex);
~MixerLine();
}
This is the code that calls the constructor (MixerDevice.cpp):
void MixerDevice::enumerateLines() {
DWORD numLines = getDestinationCount();
for(DWORD i=0;i<numLines;i++) {
MixerLine mixerLine( this, i );
// other code here removed
}
}
Compilation of MixerDevice.cpp fails with this error:
Error 3 error C2664: 'MixerLine::MixerLine(const MixerDevice &,DWORD)' : cannot convert parameter 1 from 'MixerDevice *const ' to 'const MixerDevice &'
But I thought pointer values could be assigned to references, e.g.
Foo* foo = new Foo();
Foo& bar = foo;
this is a pointer, to get a reference you have to dereference (*this) it:
MixerLine mixerLine( *this, i );
You should dereference this, because this is a pointer, not a reference. To correct your code you should write
for(DWORD i=0;i<numLines;i++) {
MixerLine mixerLine( *this, i ); // Ok, this dereferenced
// other code here removed
}
Note: the second const at the constructor's parameter const MixerDevice& const parentMixer is completely useless.
To obtain a reference from a pointer you need to dereference the pointer, as it has already been mentioned. Additionally (maybe due to copying into the question?) the constructor should not compile:
const MixerDevice& const parentMixer
That is not a proper type, references cannot be const qualified, only the referred type can be, so the two (exactly equivalent) options are:
const MixerDevice& parentMixer
MixerDevice const& parentMixer
(Note that the const qualifying of MixerDevice can be done at either way, and it means exactly the same).
Pointer values can be assigned to pointers, but not to references!1
Foo* foo = new Foo();
Foo& bar = *foo;
^
^
1. Well, they can be used to initialise references-to-pointers, but that's not what you have here...