I wanted to understand how the inline member variable work while accessing it through a const member variable.
Each time I try doing so, I get an error!
This is what I am trying
#include <iostream>
#include <string>
using namespace std;
class A{
public:
A()
{
_uuid = 0;
}
~A();
void setUUID(int n) { _uuid = n; }
inline int getUUID(){ return _uuid;} const
int getUUID1() const { return _uuid;}
int getUUIDsmart()const
{
return _uuid;
}
private:
int _uuid;
};
class B {
public:
B(){}
~B();
void fun1(const A *obj)
{
cout<<obj->getUUIDsmart()<<endl; //works fine
cout<<obj->getUUID1()<<endl; //works fine
cout<<obj->getUUID()<<endl; //error
A *obj1 = const_cast<A *>(obj);
cout<<obj1->getUUID()<<endl; //works fine
}
};
int main()
{
B *b = new B;
A *a = new A;
a->setUUID(12);
b->fun1(a);
}
I am able to get my code work through
const_cast
But I am interested in knowing why do i get an error in the inline function if I try accessing it through a const member function?
Update: FIX
My bad. I had the placement of const messed up!
Thanks to #bruno
inline int getUUID() const { return _uuid; }
//correct syntax. i placed the const at the end
[note : I use the first version of the question]
you place wrongly your const :
inline int getUUID(){ return _uuid;} const
int getUUID1(){ return _uuid;} const
int getUUIDsmart()const
is in fact
inline int getUUID(){ return _uuid;}
const int getUUID1(){ return _uuid;}
const int getUUIDsmart()const
I just moved the const on the right line for readability reason
You wanted
inline int getUUID() const { return _uuid;}
int getUUID1() const{ return _uuid;}
in your version none of getUUID1 nor getUUID are const so you cannot apply them on a const instance
There is no link at all with the fact your methods are inline or not.
Note :
cout<<obj->getUUID1()<<endl; //works fine
it doesn't
Related
Consider the following code:
#include <iostream >
using namespace std;
class A
{
private:
int x;
public:
A(int _x) { x = _x; }
int get() { return x; }
};
class B
{
static A a;
public:
static int get()
{ return a.get(); }
};
A B::a(0);
int main(void)
{
B b;
cout << b.get();
return 0;
}
My book says:
If we do not use the line of code A B::a(0),there is a compiler error because static member a is not defined in B. To fix the error, we need to explicitly define a.
However, I thought of initializing object a as static A a(0); but it gives me a compiler error. Can someone explain why I can't initialize object a in the manner I described, and why it is necessary to initialize it as they had given it in book.
If you want to define a inline, you need to inline it, which is possible from C++17:
class B {
inline static A a{0}; // or inline static A a = 0;
public:
static int get() { return a.get(); }
};
Demo
Current get() member function in class MyClass is defined as below, the return type is const int&. My question is what would be the difference if I defined get() function as
int& get() const
or
int get() const
? And which way is recommended?
#include <iostream>
using namespace std;
class MyClass {
int x;
public:
MyClass(int val) : x(val) {}
const int& get() const {return x;}
};
void print (const MyClass& arg) {
cout << arg.get() << '\n';
}
int main() {
MyClass foo (10);
print(foo);
return 0;
}
There's really nothing wrong with this code; logically it accomplishes more or less the same thing after the compiler inlines the get() method.
There's quite a big difference in some degenerate callers though:
const int *iptr = &foo.get(); // returns the address of x in the class.
On the other hand had you declared as follows:
class MyClass {
int x;
public:
MyClass(int val) : x(val) {}
const int get() const {return x;}
};
const int *iptr = &foo.get(); // Error!
I don't see any good reason for int& here. If you don't have one, people will frown on this code. Normally if people are expected to keep pointers to things around you don't return them by reference. The only reason you would want to return a pointer to a member is so that somebody can auto-pickup changes to it; and I have never seen a good use for that though I can imagine why some such thing might exist.
As for selbie's comment about assigning to it; it's a const reference; assigning to it is a compile time error.
I would like the compiler to enforce const-ness of an lvalue (non-reference) but don't know if this is possible in C++. An example:
int foo() { return 5; }
int main() {
// Is there anything I can add to the declaration of foo()
// that would make the following cause a compile-error?
int a = foo();
// Whereas this compiles fine.
const int a = foo();
}
This is not really possible with something like an int because you need to give access to read the int and if they can read the int then they can copy it into a non-const int.
But from your comments it sounds like what you have in reality is not an int but a more complex user defined type, some sort of container perhaps. You can easily create an immutable container. This container could be a wrapper, or alternative implementation of your existing container. It then doesn't matter if the caller uses a const or non-const variable it is still immutable.
class MyClass {
std::vector<int> data;
public:
MyClass(size_t size) : data(size) {}
int& operator[](size_t index) { return data[index]; }
int operator[](size_t index) const { return data[index]; }
size_t size() const { return data.size(); }
};
class MyClassImmutable {
MyClass mc;
public:
MyClassImmutable(MyClass&& mc) : mc(std::move(mc)){}
int operator[](size_t index) const { return mc[index]; }
size_t size() const { return mc.size(); }
const MyClass& get() const { return mc; }
};
MyClassImmutable foo() {
MyClass mc(100);
mc[10] = 3;
return mc;
}
void func(const MyClass& mc);
int main() {
MyClassImmutable mci = foo();
std::cout << mci[10] << "\n"; // Can read individual values
//mci[10] = 4; // Error immutable
func(mc.get()); // call function taking a const MyClass&
}
Live demo.
Of course there is nothing to stop the caller from copying each and every value from your immutable container and inserting them into a mutable container.
Edit: An alternative approach might be to return a smart pointer-to-const. The only downside is you have to pay for a dynamic memory allocation:
std::unique_ptr<const MyClass> foo() {
auto mc = std::make_unique<MyClass>(100);
(*mc)[10] = 3;
return mc;
}
void func(const MyClass& mc);
int main() {
auto mc = foo();
std::cout << (*mc)[10] << "\n"; // Can read individual values
//(*mc)[10] = 4; // Error const
func(*mc); // can pass to a function taking a const MyClass&
}
It's not possible. foo() has no way of knowing about the type of the left hand side of the assignment, because when the assignment itself happens, foo() is already evaluated. The best you could hope for is to change the return value, to try and cause a type-based error on the initialization:
#include <type_traits>
struct my_int {
const int m;
template<typename T, typename std::enable_if<std::is_const<T>::value, T>::type* = nullptr>
constexpr operator T() const {return m;}
};
constexpr my_int foo() { return {5};}
int main() {
const int a = foo();
int b = foo();
}
Live example
But this will also not work, because the typename in the template will never be substitued by a const-qualified type (in this specific case, it will be int for both lines in main()).
As the following is possible
const int x = 4;
int y = x;
the C++ language will not provide such a mechanism.
Remains making a int const by a macro mechanism.
#define int_const_foo(var) const int var = ___foo()
int_const_foo(a);
Drawback: foo cannot be hidden, and the syntax is no longer C style.
I have the following code
#include<iostream>
using namespace std;
class operate
{
int x;
int y;
public:
operate(int _x, int _y):x(_x), y(_y)
{}
void add(const char* ch)
{
cout<<ch<<" "<<x+y;
}
void subtract(const char* ch)
{
cout<<ch<<" "<<x-y;
}
void multiply(const char* ch)
{
cout<<ch<<" "<<x*y;
}
};
int main()
{
void (operate::*fptr[3])(const char*);
operate obj(2,3);
fptr[0] = &(operate.add); //problem
fptr[1] = &(operate.multiply); //problem
fptr[2] = &(operate.subtract); //problem
(obj.*fptr[0])("adding");
(obj.*fptr[1])("multiplying");
(obj.*fptr[2])("subtracting");
}
It seems I am not assigning the member functions to function pointer array properly. How can I solve this. I'm using VS2010
The dot (member-of) operator is used for accessing members of an object. For classes and namespaces, you have to use the :: operator. Also, don't parenthesize, since & has lower precedence than :: and it's more readable like
fptr[0] = &operate::add;
This should do the job
void testFP()
{
typedef void (operate::*memFP)(const char*);
memFP fptr[3];
fptr[0] = &operate::add;
fptr[1] = &operate::multiply;
fptr[2] = &operate::subtract;
operate op(42, 42);
(op.*(fptr[0]))("adding");
}
Why can't I use the function ColPeekHeight() as an l-value?
class View
{
public:
int ColPeekHeight(){ return _colPeekFaceUpHeight; }
void ColPeekHeight( int i ) { _colPeekFaceUpHeight = i; }
private:
int _colPeekFaceUpHeight;
};
...
{
if( v.ColPeekHeight() > 0.04*_heightTable )
v.ColPeekHeight()-=peek;
}
The compiler complains at v.ColPeekHeight()-=peek. How can I make ColPeekHeight() an l-value?
Return the member variable by reference:
int& ColPeekHeight(){ return _colPeekFaceUpHeight; }
To make your class a good one, define a const version of the function:
const int& ColPeekHeight() const { return _colPeekFaceUpHeight; }
when I declare the function with the
two consts
When you want to pass an object into a function that you don't expect it to modify your object. Take this example:
struct myclass
{
int x;
int& return_x() { return x; }
const int& return_x() const { return x; }
};
void fun(const myclass& obj);
int main()
{
myclass o;
o.return_x() = 5;
fun(o);
}
void fun(const myclass& obj)
{
obj.return_x() = 5; // compile-error, a const object can't be modified
std::cout << obj.return_x(); // OK, No one is trying to modify obj
}
If you pass your objects to functions, then you might not want to change them actually all the time. So, to guard your self against this kind of change, you declare const version of your member functions. It doesn't have to be that every member function has two versions! It depends on the function it self, is it modifying function by nature :)
The first const says that the returned value is constant. The second const says that the member function return_x doesn't change the object(read only).
It can be rewritten like:
class View
{
public:
int GetColPeekHeight() const { return _colPeekFaceUpHeight; }
void SetColPeekHeight( int i ) { _colPeekFaceUpHeight = i; }
private:
int _colPeekFaceUpHeight;
};
...
{
cph = v.GetColPeekHeight();
if ( cph > 0.04 * _heightTable )
v.SetColPeekHeight( cph - peek );
}