I am trying to write a class Core, it's member variable is a pointer. The copy constructor is Core(Core& x) instead of Core(const Core& x).
Core has a member function Core Core::new_core (int * ptr), the code has a problem when I try to construct Core new_core= core.new_core(ptr);, please see the code and error information below.
#include<iostream>
class Core
{
private:
int* a;
public:
Core(int* in) {a=in;}
Core(Core& x) {a = x.data();}
inline const int * data() const {return a;}
inline int * data() {return a;}
Core new_core (int * ptr)
{
Core b(ptr);
return b;
}
};
using namespace std;
int main()
{
int ptr[3]= {1,2,3};
Core core(ptr);
Core new_core= core.new_core(ptr);
cout<< new_core.data() <<endl;
return 0;
}
Error information:
main.cpp: In function ‘int main()’:
main.cpp:30:37: error: no matching function for call to ‘Core::Core(Core)’
Core new_core= core.new_core(ptr);
^
main.cpp:30:37: note: candidates are:
main.cpp:12:6: note: Core::Core(Core&)
Core(Core& x) { a = x.data() ;}
^
main.cpp:12:6: note: no known conversion for argument 1 from ‘Core’ to >‘Core&’
main.cpp:10:6: note: Core::Core(int*)
Core(int* in) {a=in;}
^
main.cpp:10:6: note: no known conversion for argument 1 from ‘Core’ to
‘int*’
I can easily fix the problem by replacing
Core(Core& x) { a = x.data() ;}
to
Core(const Core& x) { a = const_cast<int* > ( x.data() ) ;},
is there a better way to solve the problem without using const_cast?
I want to keep int* a private, and keep following two lines:
inline const int * data() const {return a;}
inline int * data() {return a;}
Thank you.
The problem here is that new_core returns a Core which is a temporary. When you use it in
Core new_core= core.new_core(ptr);
The compiler calls the copy constructor but it cannot bind to that temporary since it takes a reference. To fix this we can change the copy constructor to take a const Core& which can bind to the temporary and allow you to make a copy.
In this example to get around the const and the use ofconst_cast we can access the class member directly like:
Core(const Core& x) : a(x.a) {}
Related
The example generates the error
the object has type qualifiers that are not compatible with the member
function
and I can't figure out why.
A.h
class A {
public:
void f2(XXX* ..) const;
protected:
const vector<XYZ> f(){return m;}
vector<XYZ> m;
}
A.cpp
void A::f2(XXX* ..) const
{
const vector<XYZ>& P= this->f(); // Here I get this error as well
}
Can someone explain me what I've done wrong?
Thanks.
You can't call a non-const function from a const function. This means that f needs to be const qualified as well:
const std::vector<XYZ> f() const { return m; }
otherwise you can't call it from f2.
I have a class B that has two methods, where one returns a pointer to a member variable and the other returns a const reference to the variable.
I try to call those methods. During the calls, I store the return values to respective return types.
I was expecting the appropriate return types would end up calling the appropriate methods, but I get a compilation error saying:
error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
const int& refval2 = b.Get(); `
Here is my code:
#include <iostream>
class B{
public:
int* Get(){
return &x_;
}
const int & Get() const{
return x_;
}
private:
int x_ = 0;
};
int main(){
B b;
const int& refval2 = b.Get();
int* pval2 = b.Get();
}
Return type is not part of function signature, it's not considered in overload resolution.
In general, the candidate function whose parameters match the arguments most closely is the one that is called.
For non-static member function call, the type of the object to be called on involves too. There're two Get(), one is const and one is non-const. For b.Get();, the non-const Get() is an exact match; for the const Get() to be called the object b has to be converted to const. Then the non-const one wins, after that the compiler will try to convert the returned int* to const int& and fails.
So
B b;
int* pval2 = b.Get(); // call to non-const Get()
const B cb;
const int& refval2 = cb.Get(); // call to const Get()
Why is the int* Get() called insted of const int& Get()?
const int & Get() const
Is a const member function.
From class.this:
If the member function is declared const, the type of this is const X*
However, you declared:
B b;
as non-const which will call the non-const function int* Get(). Thus, the error.
There are two things
return type are not considered in overload resolution
Const ness of method is considered in over load resolution
If you remove const in second method, compiler will complain about ambiguity.
As already answered return type is not considered. So I see 3 possible solutions:
1 make it part of function signature:
class B {
public:
void Get( int *&refptr );
void Get( int &refval ) const;
};
int main(){
B b;
int refval2 = 0;
b.Get( refval2 );
int* pval2 = nullptr;
b.Get( pval2 );
}
but this produces pretty ugly code, so you better use method 2 or 3 -
2 use different function names, this is pretty obvious
3 use ignored parameter:
class B {
public:
int *Get( nullptr_t );
const int &Get() const;
};
int main(){
B b;
const int &refval2 = b.Get();
int* pval2 = b.Get( nullptr );
}
The problem is that the compiler thinks the two Get() functions are the same. If you create two identical functions with only varying return types, the compiler has no idea which function you want to use. To fix the problem, change the name of one or both of the Get() functions; say GetXPtr() and GetX().
The following code compiles fine.
#include <iostream>
#include <vector>
using namespace std;
class MyClass
{
public:
MyClass()
{
x.resize(2);
x[0] = 10;
x[1] = 100;
}
std::vector<int> getValue()
{
return x;
}
const std::vector<int>& getValue() const
{
return x;
}
private:
std::vector<int> x;
};
int main()
{
MyClass m;
std::vector<int> y = m.getValue();
for(int i=0; i<y.size(); i++)
{
std::cout<<y[i]<<std::endl;
}
const std::vector<int>& z = m.getValue();
for(int i=0; i<z.size(); i++)
{
std::cout<<z[i]<<std::endl;
}
return 0;
}
However, when I change the "std::vector getValue()" to a more correct version (since the function is supposed to change the object) by adding "const" (std::vector getValue() const) it gives the following compilation error.
error: 'const std::vector<int>& MyClass::getValue() const' cannot be overloaded const std::vector<int>& getValue() const
Why is it so?
I have used "gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)"
You can't define two functions with the same name, which differ only in return type. So define function with different name, for example:
std::vector<int> getValueCopy() const;
By adding const to the first function you render calls to getValue ambiguous: What is the difference between those 2 functions:
std::vector<int> getValue() const; // 1
const std::vector<int>& getValue() const; // 2
Well, they are the same, except for the return value, but wait! You can't overload based on the return type in C++! It wouldn't make sense, most calls would be ambiguous:
std::vector<int> y = m.getValue(); // which one? It can be 1, it can be 2 (std::vector<int>
// is not a better match than const std::vector<int>&)
const std::vector<int>& z = m.getValue(); // same as above
m.getValue(); // which one?
But also, what is supposed to be the difference between the two?
The first one is 100% safe, while the second one is not: one could store a reference to x, and it becomes a dangling reference if the object gets destroyed. And so I would say that you get rid of the second one, if possible.
your problem is that you didn't understand functions overloading concept
when you overload function The definition of the function must differ from each other by the types of argument or the number of arguments in the argument list.
You can not overload function declarations that differ only by return type.
in your functions :
std::vector<int> getValue() const
const std::vector<int>& getValue() const
it only differ in return type so it will be not considered as overloaded functions
best way to correct your error is to change your second function name to getValuev2()
or change arguments of one of the functions.
you can read more about overloading in C++ :
https://www.tutorialspoint.com/cplusplus/cpp_overloading.htm
I have an overloaded member function in single class. The differences between two return type and const modifier:
class A
{
public:
int mass() const {return m_mass;}
protected:
int& mass() {return m_mass;}
private:
int m_mass;
};
But by default having non-const instance of class A will cause non-const version of overloaded function to be called:
int main()
{
A a;
return (const int)a.mass();
}
error: int& A::mass() is protected within this context
How can the const version be called explicitly in this case?
You simply use a named const reference to it, or better still, use const_cast to obtain an unnamed const reference to it, then call.
int main()
{
A a;
//1
const A& a_const = a;
a_const.mass();
//2
const_cast<const A&>(a).mass();
//3
//in C++17
//std::as_const(a).mass(); //3
}
With C++17 and later you can use std::as_const.
C++17 will introduce std::as_const, which is a really simple utility that you can implement yourself until then:
A a;
std::as_const(a).mass();
Problem: source code (see. below) is compiled MSVC , but does not compile g++.
#include <iostream>
using namespace std;
class B;
class A
{
friend class B;
private:
int i;
A(int n) : i(n) { }
public :
A(A& a) { if (&a != this) *this = a; }
int display() { return i;}
};
class B
{
public :
B() { }
A func( int j) { return A(j); }
};
int main(int argc, char **argv)
{
B b;
A a(b.func((10)));
cout << " a.i = " << a.display() << endl;
return 0;
}
Output:
GNU g++ compilation message:
g++ -c main.cpp
main.cpp: In member function 'A B::func(int)':
main.cpp:25:38: error: no matching function for call to 'A::A(A)'
A func( int j) { return A(j); }
^
main.cpp:25:38: note: candidates are:
main.cpp:17:9: note: A::A(A&)
A(A& a) { if (&a != this) \*this = a; }
^
main.cpp:17:9: note: no known conversion for argument 1 from 'A' to 'A&'
main.cpp:14:9: note: A::A(int)
A(int n) : i(n) { }
^
main.cpp:14:9: note: no known conversion for argument 1 from 'A' to 'int'
main.cpp: In function 'int main(int, char\**)':
...
Why? Class B is a friend for class A then B has access to private constructor A(int i).
Your copy constructor must take a const reference so it can bind to a temporary A:
A(const A& a) { .... }
The C++ standard does not allow binding a non-const reference to a temporary. g++ is strict about this, while MSVC has an "extension" that breaks the rule.
Besides that, your implementation of the copy constructor looks strange. You should not be using the assignment operator there. For a class like A, you should use the implicitly generated copy constructor, in other words, remove your own:
class A
{
friend class B;
private:
int i;
A(int n) : i(n) { }
public :
int display() const { return i;}
};
It is a bug of MS VC++. It shall not compile the code. The problem is that the error message of g++ is not cllear enough.
In fact the compiler tries to elide using of a copy constructor and to build the object directly in 'a' using constructor A(int n);. But that it will be possible an appropriate copy constructor shall be available. As a temporary object should be copied (if the ilision would not be used) then the copy constructor shall have const reference to object. That is instead of A(A& a); your copy constructor shall be declared as A( const A& a); If you will make the changes then g++ will compile the code.
The most simple way to define copy constructor for your example is to write
A( const A & ) = default;
However I am not sure whether your MS VC++ compiler supports this feature.