How is it possible to assign "this" pointer to field? - c++

As far as I know, "this" pointer is the parameter that is inserted into function by Compiler like below :
class Sample {
private:
int a;
public:
void setA(int a) {
this->a = a;
}
};
Sample ob;
ob.setA(5); -> ob.setA(&ob, 5);
class Sample {
private:
int a;
public:
void setA(Sample* this, int a) {
this->a = a;
}
};
Btw, I found something confusing code that assigning the "this" pointer to const field. (Consult below)
class Test {
int data;
public:
Test* const test = this;
Test(int data = 1) : data(data) { }
Test(Test &test) : data(test.data) { }
};
(It has no compile Errors and runs well!)
If it is true that "this" pointer is conveyed via function, How can it be?
I have no idea..
Could you give me some advice please? I'm appreciate for your any replies.

This syntax:
Test* const test = this;
comes from C++11. It means "initialize test to this inside any non-copy constructor which does not already initialize test explicitly".
As a result, this code is executed inside the constructor, and this is perfectly valid. However, the benefit of doing this sort of initialization is unclear, and dependening on the usage of test might be dangerous.

The properties of the class (Test.test in this case) are initialized implicitly by code that is generated by the compiler. There is a function, and it does receive the this pointer, but it's all generated by the compiler which is why you can't see it.

Related

Can I make a variable _const from now on_?

I'm using a library that has a class with an init function distinct from its constructor. Every time I make a new instance I need to call, for example:
MyClass a;
a.init();
Since init is not const, this prevents me from creating const instances (I can't write const MyClass a). Is there some way to call init and then declare from "here on out" (I guess for the remainder of the scope) my variable is const?
This works, but relies on not touching the original variable:
MyClass dont_touch;
dont_touch.init();
const MyClass & a = dont_touch;
If you're using C++11 you could use a lambda function
const MyClass ConstantVal = []{
MyClass a;
a.init();
return a;
}();
This allows you to keep the initialization in place while never giving outside access to the mutable object.
see also:
http://herbsutter.com/2013/04/05/complex-initialization-for-a-const-variable/
You can create a wrapper class and use that instead.
If MyClass has a virtual destructor you can feel safe deriving from it like this:
class WrapperClass : public MyClass
{
public:
WrapperClass()
{
init(); // Let's hope this function doesn't throw
}
};
Or write a class that contains the MyClass instance
class WrapperClass
{
public:
WrapperClass()
{
m_myClass.init(); // Let's hope this function doesn't throw
}
operator MyClass&() {return m_myClass;}
operator const MyClass&() const {return m_myClass;}
private:
MyClass m_myClass;
};
Or write a template to solve this general problem using one of the two solutions above: eg.
template <class T> class WrapperClass : public T
{
public:
WrapperClass()
{
T::init();
}
};
typedef WrapperClass<MyClass> WrapperClass;
Create a function that wraps the first two lines and gives you an object that is ready to go.
MyClass makeMyClass()
{
MyClass a;
a.init();
return a;
}
// Now you can construct a const object or non-const object.
const MyClass a = makeMyClass();
MyClass b = makeMyClass();
Update
Using makeMyClass() involves construction and destruction of a temporary object everytime the function is called. If that becomes a significant cost, makeMyClass() can be altered to:
MyClass const& makeMyClass()
{
static bool inited = false;
static MyClass a;
if ( !inited )
{
inited = true;
a.init();
}
return a;
}
It's usage, as described earlier, will continue to work. In addition, once can also do this:
const MyClass& c = makeMyClass();
You can actually do it quite simply, even without C++11 and lambdas:
const MyClass a;
{
MyClass _a;
_a.init();
std::swap(const_cast<MyClass&>(a), _a);
}
The use of const_cast is admittedly a bit of a hack, but it won't break anything as const is quite a weak specifier. At the same time, it is quite efficient, as the MyClass object is only swapped, not copied (most reasonable expensive-to-copy objects should provide a swap function and inject an overload of std::swap).
Without the cast, it would require a helper:
struct Construct_Init {
operator MyClass() const
{
MyClass a;
a.init();
return a;
}
};
const MyClass a = Construct_Init();
This can be like this in a function (the Construct_Init structure needs not be declared at namespace scope), but it is a bit longer. The copy of the object may or may not be optimized away using copy elision.
Note that in both cases, the return value of init() is lost. If it returns a boolean where true is success and false is failure, it is better to:
if(!a.init())
throw std::runtime_error("MyClass init failed");
Or just make sure to handle the errors appropriately.

Memory allocation and releasing memory

I'm a newbie using V++ and I've been wondering about some memory behavior.
I wrote similar classes to what is causing me problems. The questions are
written in the comments of the code.
class A
{
private:
int _number;
public:
A(int number) : _number(number)
{}
const int& getNumber() const
{
return _number;
}
void setNumber(const int& number)
{
_number = number;
}
}
class B
{
private:
A _a;
bool _hasA;
public:
B() : _hasA(false)
{}
B(const A & a) : _a(a), _hasA(true)
{}
void setA(const A & a)
{
_a = a;
}
const A& getA() const
{
return _a;
}
const bool hasA() const
{
return _hasA;
}
void removeA()
{
// ??
}
}
int main()
{
A a(5);
B b1; // Is the A space allocated even if no value is affected to it ?
B b2(a);
b1.setA(b2.getA()); // I actually want to move "a" from b2 to b1 without leaving it in b2
b1.removeA(); // Do I need to write a removeA() function and how would it be?
}
b1.setA(b2.getA()); copies A into b1 too instead of moving it.
Thanks for your help.
EDIT: To answer those who are confused like I just was:
Me : I just understood that when instanciating b1 it needed the A::A() constructor. I thought it'd be like "null" or something if I created b1 without instantiating _a.
Zac Howland: #SanjamX I see your confusion now. In managed languages, (most) everything is a pointer, so if you do not instantiate it (e.g. A a instead of A a = new A()), it is just a null pointer. In C/C++, if you declare something as A a, you instantiated it "on the stack". It is an automatic variable that will be deallocated when it goes out of scope. You are still instantiating it, however. This question may help you understand better.
B b1();
That does not do what you think it does. It is declaring a function b1 that takes no parameters and returns a B.
b1.setA(b2.getA());
b1.removeA();
Because of the previous situation, the 2 lines above will give you a compiler error.
The "move" you are asking about will actually be a copy (in this case). You can use the C++11 move semantics to do an actual move, but it is entirely unnecessary with the current code. Alternatively, you can change your class to do a move using pointers (which could potentially be useful) - which would use std::unique_ptr<A> _a, instead of A _a.

Polymorphism Problem C++

I have these classes:
class A
{
};
class B : public A
{
public:
B(int val);
private:
int* m_int;
};
B::B(int val)
{
m_int = &val;
}
I call the code like so, inside 1 function, i know the vars will be destroyed once they are out of scope, but I only need them in this function:
{
...
int _int = 0;
B obj(_int);
A *obj2 = &obj;
_int++;
...
}
The problem is that _int is changing to 1, but m_int stays the same. I need m_int to reflect what the value in _int is, without the need to update it with code. I thought having a pointer to a memory location would work?
The second problem is that when I hover my mouse over obj2, to see the values of obj, I get the message "children could not be evaluated".
I'm not too sure whether the following is good advice for a novice, but using a reference like this would work:
class B : A
{
public:
explicit B(int& val);
private:
int* m_int;
};
B::B(int& val)
{
m_int = &val;
}
I'm a bit worried that it is actually a sign of bad design. If it is just for learning purposes, go right ahead, understanding is always important
The pointer m_int will stay the same but the value pointed to *m_int will change, you'll also have to pass the value val by reference to the function.
EDIT: Saw your edited question, since this is done from the constructor you can do:
class B : A
{
public:
B(int& val) : m_int(val) {}
private:
int& m_int;
};
To have m_int reference the same variable.
If you want to change value of _int you should pass it's pointer, they way you're doing now is call by value.
B::B(int* val)
{
m_int = val; // not ref
}
and m_int should be of type int* not int
For second problem, you're storing a value of derived class in a pointer to base, So when you try to see what's inside obj2 you only see the part of type base, that's why you get message children cannot be evaluated.
Edit--
If you want to see what actually is in obj2, you should cast it to derived type again. And you may not always know that at runtime...

Error : 'CPtrList::AddTail' : 2 overloads have no legal conversion for 'this' pointer

How to overcome this?
Here is my code
Here is my code
ObjectList.h
#pragma once
#include "LogData.h"
typedef CTypedPtrArray<CPtrList , CLog *> CLogData;
class CObjectList
{
public:
CLogData m_logData;
public:
CObjectList();
CLogData GetLog();
};
ObjectList.cpp
#include "stdafx.h"
#include "LogData.h"
CObjectList::CObjectList()
{
}
CLogData CObjectList::GetLog()
{
return m_logData;
}
While access the content in another file like these show error:
CObjectList* threadinfo;
threadinfo = (CObjectList*)ptr;
threadinfo->GetLog().AddTail(log);
Regards,
Karthik
It is very hard to tell, seeing as your post is very disjointed.
The error message sounds like one you get when you try to violate const-ness.
e.g.
class C
{
public:
void a();
void b() const;
};
void func()
{
C c0;
c0.a(); // OK
c0.b(); // OK
const C c1;
c1.a(); // violates const-ness : compiler error
c0.b(); // this is OK as b() is a const function.
}
If you have a const object, you can only call const methods.
You get many variations on this. e.g.
class D
{
public:
void e();
};
class F
{
public:
void g() const
{
m_d.e(); // This line is an error
}
D m_d;
};
void func()
{
F f;
f.g();
}
In the above, F::g() is a const function. It may be called on const objects. But even if you call it with a non-const object, it guarantees not to change the object.
But F::g() calls D::e() on the local object m_d. D:e() is not a const function, so the compiler doesn't know if it will modify m_d -- therefore the compiler will give an error.
It can get complex.
So I guess that you have a problem with const-ness. It might be a straightforward one or it may be a complex one. If you can post some complete code that shows the same problem, then it will be easier to help you.

Non static members as default parameters in C++

I'm refactoring a large amount of code where I have to add an extra parameter to a number of functions, which will always have a value of a member of that object. Something like
class MyClass
{
public:
CMyObject A,B;
void MyFunc(CMyObject &Object);
// used to be void MyFunc();
};
Now, I'd actually like it to read
class MyClass
{
public:
CMyObject A,B;
void MyFunc(CMyObject &Object = A);
};
But I'm not allowed to have a default parameter that is a non-static member. I've read this similar question which suggest this isn't possible, but I'm wondering if there is any reasonable workaround. Reason being that 95% of the time the default parameter will be used, and thus using a default parameter would hugely reduce the amount of code I have to change. My best solution so far is something like this;
class MyClass
{
public:
CMyObject A,B;
void MyFunc(BOOL IsA = TRUE);
};
void MyClass::MyFunc(BOOL IsA)
{
CMyObject &Object = A;
if (!IsA)
Object = &B;
}
This is less than elgant, but is there a better way of doing this that I'm missing?
Edit: FWIW, the reason for the extra parameter is to externalize some state related members from the object in question to aid multi-threading.
How about :
class MyClass
{
public:
CMyObject A,B;
void MyFunc()
{
MyFunc(A);
}
void MyFunc(CMyObject &Object);
};
?
Another way:
class MyClass
{
public:
MyObject A,B;
void MyFunc(MyObject MyClass::*myObject = &MyClass::A) {
MyObject& obj = *(this->*myObject);
}
};
This makes it even impossible to pass in an MyObject member from another MyClass instance. Your three valid options to call MyFunc are .MyFunc(), .MyFunc(&MyClass::A) and .MyFunc(&MyClass::B)