C++ class object pointers and accessing member functions - c++

I'm bit new to C++ and try to work things with Qt and came across this confusing thing:
The concepts on various tutorials state something like:
Class *obj;
*obj - will display the value of object stored at the referenced memory
obj - will be address of memory to which it is pointing
so, I would do something like
*obj=new Class();
but if I want to access a function, I have to do obj->function1();
instead of *obj->function1();
-- not sure why, since with normal objects [ normalObj.function1();] would work, since that's the value directly.
So, for pointer objects why do we use memory reference to access the function,
or is it that in case of normal objects also, its always references
P.S: Can someone guide me to a good tutorial of usage of pointers in C++, so that my queries like these can be directly addressed in it.

The * symbol is used to define a pointer and to dereference a pointer. For example, if I wanted to create a pointer to an int, I could do:
int *ptr;
In this example, the * is being used to declare that this is a pointer to an int. Now, when you are not declaring a pointer and you use the * symbol with an already declared pointer, then you are dereferencing it. As you probably know, a pointer is simply an address. When you dereference a pointer, you are obtaining the value that is being pointed to by that address. For example:
int pointToMe = 5;
int *ptr = &pointToMe;
std::cout << *ptr;
This will print out 5. Also, if you are assigning a pointer to a new address and it's not in the declaration, you do not use the * symbol. So:
int pointToMe = 5;
int *ptr;
ptr = &pointToMe;
is how you would do it. You can also deference the pointer to assign a new value to the value being pointed to by the address. Such as:
int pointToMe = 5;
int *ptr = &pointToMe;
std::cout << *ptr; // Prints out 5
*ptr = 27;
std::cout << *ptr; // Prints out 27
Now, -> acts like the deference symbol. It will dereference the pointer and then use the member functions and variables as if you had used . with a non-pointer object. Even with an object that is not a pointer you can use the -> by first getting the address:
CObj object;
(&object)->MemberFunction();
That's just a brief overview of pointers, hope it helps.

You can use the "normal" . to access the objects members, but you have to dereference the pointer first.
Due to operator precedence, this will look like (*obj).member. For those who think this is too much to write, obj->member is a shorter alternative.
If you have an object c of type Class, *c.ptr means dereferencing a pointer ptr that is a member of Class. That is one reason for (*obj).member, which means something else.

Actually, you're wrong. You do:
obj=new Class();
or
Class *obj = new Class;
which are completely different.
Class *obj;
*obj = new Class;
wouldn't compile.
obj is of type Class*, so that's what you can assign to it (and what new Class returns).

More precisely u can do like this
Class obj;
Class* obj_ptr;
obj_ptr = &obj;
// Now onwards you can use the pointer to access data members and function
obj_ptr->a = 10; // Like this

Related

the arrow '->' separator is crashing when calling function from class

I'm working on a project for class and I'm using classes and pointers of type class to call some functions in the class but it's crashing on Code Blocks and Eclipse and I don't know what is going on
Note it crashes when assigning x with y
#include <iostream>
using namespace std;
class a{
private:
int x;
public:
void set_X(int y){
x=y;
}
};
int main()
{
a *Ptr;
Ptr->set_X(5);
}
a *Ptr;
Ptr->set_X(5);
Your Ptr does not point to anything. Trying to invoke a member function on an uninitialised pointer results in undefined behaviour. Crashing is just one of the many more or less random things that can happen.
Luckily, in your example, you do not need a pointer anyway. You can simply write:
a my_a;
my_a.set_X(5);
Pointers often point to dynamically allocated objects. If this is what you want, you must use new and delete accordingly:
a *Ptr = new a;
Ptr->set_X(5);
delete Ptr;
In modern C++, std::unique_ptr is typically a superior alternative because you don't have to manually release the allocated memory, which removes a lot of potential programming errors:
auto Ptr = std::make_unique<a>();
Ptr->set_X(5);
// no delete necessary
Basic rule: creating a pointer (a variable that contains the address of an object, or otherwise is NULL (or nullptr since 2011)) as pointed out by Christian Hackl in comments) does not create a corresponding pointee (an object who's address can be stored in the pointer).
More formally, Ptr is an uninitialised pointer. Even accessing its value gives undefined behaviour (e.g. some_other_pointer = Ptr). For operator -> to work correctly, the pointer must first be initialised so it points at a valid object.
a aobj;
a *Ptr = &aobj;
Ptr->set_X(42); // OK
a *Ptr2 = new a;
Ptr2->set_X(42); // OK
delete Ptr2;
You have just declared a pointer variable of type a* but it doesn't point to a valid memory address. And since you are calling a member function via that pointer which updates a data-member hence you have segfault because this pointer is NULL.
You must initialize pointer with some valid memory address of class a object.
Following can be done,
a* ptr = new a;
ptr->set_X(5);
// ...
delete ptr;
In this case. It would be better that you should use some smart_ptr like std::shared_ptr or std::unique_ptr so that you don't need to worry about releasing resources manually.
Or
a* ptr;
a aobj_;
ptr = &aobj_;
ptr->set_X(5);

How to pass a pointer to function in c/cpp?

I want to pass a pointer to a function.
Lets say I am creating a structure and declare a pointer to that structure. I allocate memory to that pointer and then I want to "pass" that pointer to a function so I can do stuff to that block of memory. How I do that?
It is done the same way as passing a normal variable. You shouldn't think of a pointer any different than a variable, as a pointer is a variable (although a bit special).
Say you have an integer and a pointer to that integer:
int a = 0;
int * ptr = &a;
Note that ptr and a are both variables, and in this instance, we use the reference operator & to reference a by &a which gives the address of a -- this is a pointer to a.
Now say you have two functions:
void foo(int i){}
void bar(int * p){}
Now these two functions do the same thing (nothing), but one takes an int and one takes a pointer to an int, int *. If you called foo(a) and modified i, i would be modified in the function body, but have no effect on a. If you called bar(ptr) and modified the value pointed to by ptr by using the dereference operator * as something like *ptr = 1, it would modify the value pointed to by ptr, which in this case would be a.
In your case, passing a struct would be just the same. Say you have a structure
struct MyStruct { int b; };
And had two more functions
void structFoo(struct MyStruct m) {}
void structBar(struct MyStruct * mp) {}
You could work on the pointer in the same way as our above int and int * functions, although you would now also have to access the struct components by dereferencing the struct with (*mp).b, or the shorthand version mp->b.
For ease of use, you may also want to do something like
typedef struct MyStruct MyStruct;
Which will allow you to use MyStruct as the type name rather than requiring struct MyStruct as in the above functions, although you may want to avoid doing this until you fully understand what is happening and get through difficulties with pointers.
Hopefully that gives you some idea of what is going on, although the C++ tutorial on pointers gives a much more in-depth discussion than what I can provide.
It would be a good exercise to create some small programs and mess around with pointer and regular types while printing the results to help understand what is happening where. You should remember that to allocate a pointer, you're going to need to use either new or malloc(), otherwise you will have a SEGFAULT error. This is not an issue when referencing a variable declared as I have done with &a above as the memory is already allocated when a declaration such as int a is made. A declaration of a pointer allocates the memory for that pointer, but not the memory that it points to. This eventually leads into the difference between the stack and the heap, although I wouldn't think about that until you have a very thorough understanding of pointers.
Structure in c/cpp is like all the other types. You can use & and * as you do it for int.

(->) arrow operator and (.) dot operator , class pointer

In C++ we know that for a pointer of class we use (->) arrow operator to access the members of that class like here:
#include <iostream>
using namespace std;
class myclass{
private:
int a,b;
public:
void setdata(int i,int j){
a=i;
b=j;
}
};
int main() {
myclass *p;
p = new myclass;
p->setdata(5,6);
return 0;
}
Then I create an array of myclass.
p=new myclass[10];
when I go to access myclass members through (->) arrow operator, I get the following error:
base operand of '->' has non-pointer type 'myclass'
but while I access class members through (.) operator, it works. These things make me confused. Why do I have to use the (.) operator for an array of class?
you should read about difference between pointers and reference that might help you understand your problem.
In short, the difference is:
when you declare myclass *p it's a pointer and you can access it's members with ->, because p points to memory location.
But as soon as you call p=new myclass[10]; p starts to point to array and when you call p[n] you get a reference, which members must be accessed using ..
But if you use p->member = smth that would be the same as if you called p[0].member = smth, because number in [] is an offset from p to where search for the next array member, for example (p + 5)->member = smth would be same as p[5].member = smth
Note that for a pointer variable x
myclass *x;
*x means "get the object that x points to"
x->setdata(1, 2) is the same as (*x).setdata(1, 2) and finally
x[n] means "get the n-th object in an array".
So for example x->setdata(1, 2) is the same as x[0].setdata(1, 2).
Because by using [] like p[3] you are already dereferencing the pointer to array + index shift. After that you have to use ".", since p[3] is an object, not a pointer.
After...
MyClass* p = new myclass[10];
...p is a pointer to an array of MyClass objects. The "pointer to an array" thing has to be delt with first. Whenever you have a pointer to an array, p[n] effectively gives you a reference to the nth element in the array, so you effectively have a MyClass&. That's why . is then needed to access MyClass members ala p[n].member, and why the pointer-specific -> notation is erroneous in this case....
Note that p->member (for any member) is still valid and equivalent to p[0].member, so you can only use it for accessing the first element in the array. I strongly recommend you don't use it at all whenever you're in a programmatic context where 'p' is known to be pointer to the array, as it hides the fact that p is an array. Sometimes though you may create another pointer - say q - with the purpose of refering to a single array element - may or may not be [0] - and in those situation's it's fair to use q->member. Variables like q may be used for iteration over the array too. But, sometime you're going to need to delete[] p; - so you won't tend to change p beforehands... you don't want to lose track of the p[0] address or delete[] p; will be Undefined Behaviour (which is allowed to be implementation defined and happens to be on Windows if p still points within the array, but won't be portable).
myclass *ptr;
ptr = new myclass(); // ptr points to a single object
ptr->doSomething(); // calls doSomething on the object _pointed to_
ptr = new myclass[10]; // ptr points to multiple objects
ptr->doSomething(); // calls doSomething on the first object _pointed to_
(ptr+1)->doSomething(); // calls doSomething on the second object _pointed to_
auto val = ptr[2]; // fetches a reference to the second _object_ to val.
val.doSomething(); // calls doSomething on the _object reference_ val.
In other words, when indexing the array to fetch the n'th element, you're not fetching a pointer to the n'th element, you're fetching a reference to the actual object, and the members of that need to be accessed using . syntax.
Perhaps its insightful to consider that, given
myclass obj;
auto p = &obj; // avoid `new` with plain pointers. That combination is
// safer replaced by unique_ptr or std::vector.
the following will all work and are equivalent:
p->setdata(5, 6);
(*p).setdata(5, 6);
p[0].setdata(5, 6);
0[p].setdata(5, 6);
Showing that [] is really a pointer-dereferencing operator, just with the extra functionality that you can add offsets into a plain C-array.
It's generally questionable to use C-arrays in C++ code; the obvious alternative to your example is std::vector:
std::vector<myclass> array(10);
Here, array[n] can be used much like previously p[n], but
You don't get any stupid pointer-ideas, because there are no pointers in the interface
You get proper automatic memory management, i.e. when the array goes out of scope it automatically deletes the objects and its memory
You can get bounds-checks if you want (array.at(n))
You can easily loop over the whole array, with (C++11) for(auto& obj: array){...}.

no suitable constructor exists to convert from "test *" to "test", constructor,

I'm new to c++ and I'm having difficulties with constructor and classes. So, here is my header file:
#pragma once
#include <string>
using namespace std;
class test
{
private:
string name;
int number;
public:
test();
test(string i,int b);
};
This is cpp file:
#include "test.h"
#include <string>
using namespace std;
test::test(){}
test::test(string i,int b){
this->name=i;
this->number=b;
}
now, when I try to call
test t=new test("rrr",8);
I get:
1 IntelliSense: no suitable constructor exists to convert from "test *" to "test"
So, whats the thing with classes having * in their name ( for instance, classes without .cpp file don't have asterix, all others do)? And what do I do wrong?
I imagine you're coming from a Java/C# background. t is not a reference type here, it's a value type. new returns a pointer to an object. So you need any of the following:
test t = test("rrr", 8);
test t("rrr", 8);
test *t = new test("rrr", 8);
If you're not yet familiar with pointers, then definitely don't use the last one! But understanding the semantics of pointers is fairly critical; I recommend reading the relevant chapter(s) in your textbook...
So, whats the thing with classes having "*" in their name ( for instance, classes without .cpp file dont have asterix, all others do)???
You definitely need to learn about pointers. test * and test are two completely different types in C++. Here's two variables with those types:
test t;
test* p;
Here, t has type test, and p as type test*. We describe test* as "pointer to test".
You can often think of a pointer as being the memory address of an object. So in p, since it is a pointer, we could store the memory address of t, which is a test. To get the address of an object, we use the unary & operator, like so:
test t;
test* p = &t;
Note that t is a test object. You didn't need to say new test(). This is where C++ differs from other languages that you might have used, like C# and Java. In the above C++ code, t is a test object.
However, you can create objects with new test(), so what's the difference?
test t; creates a test object with automatic storage duration. This means it is destroyed at the end of its scope (often the function is being declared within).
new test() creates a test object with dynamic storage duration. This means you have to destroy the object manually, otherwise you'll have a memory leak. This expression returns a pointer and so you can initialise a pointer object with it:
test* p = new test();
So now let's look at your problem:
test t=new test("rrr",8);
We now know that new test("rrr", 8) returns a pointer to test (a test*). However, you're trying to assign it to a test object. You simply can't do this. One of them is an address and the other is a test. Hence the compiler says "no suitable constructor exists to convert from test * to test." Makes sense now, doesn't it?
Instead, you should prefer to use automatic storage duration. Only use new if you really really need to. So just do:
test t("rrr", 8);
test t=new test("rrr",8);
must be
// v
test* t=new test("rrr",8);
So, whats the thing with classes having "*" in their name
* is used to indicate a pointer, it's not in the name of the class. But it's a big topic, so you should do some reseach on this.
* is not part of the name, it's a modifier denoting, that the object is a pointer. A pointer is a variable holding address to some place in memory, where the actual object is stored. Some basics:
int i = 5;
int * pI = &i;
int * pI means, that you want to declare a pointer to place in memory, where an int is held. &i means, that you want to retrieve a pointer to variable. So now pI holds address in memory, where i is stored. Now you can dereference a pointer - get to value of the pointer:
int j = *pI;
Now you tell the compiler, that it should go to the address pointed to by pI and retreive its contents (since pI is a pointer to int, compiler will assume, that there's an int there).
Now, back to your example. new operator allocates memory dynamically for an object, so:
new test("rrr", 8);
results in allocating a memory for test class, calling its constructor with parameters "rrr" and 8 and returning a pointer to allocated memory. That's why you cannot assign it to test variable: new operator in this case returns a test *.
Try this code:
test * t = new test("rrr", 8);
T* t = new T;
// ^^^
When new is used in this object construction, it denotes the creation of a pointer. What are doing is dynamically allocating memory which I'm sure you didn't mean to do. The Rather, typical stack allocated object construction is done simply like this:
T t;
Even if you had intended on creating a pointer and allocating the memory, you did it the wrong way. A pointer is created with the * symbol, which you lacked in your code. Secondly, when you're done using the memory you created, you must remember to delete/delete[] your code. delete[] is used on dynamically allocated arrays. So this is how it would look for your pointer:
delete t;
You did not define t as a pointer:
test* t=new test("rrr",8);
Or just
test t = test("rrr",8);

basic pointer question in c++ program

I looking for a clarification regarding the pointers. I have compiled the following code in bordland c++ 5.5.1 without any errors. But while i am trying to execute gives a core error.
int main ()
{
int x=10,y=20;
int &a=x;
int &b=y;
int *c;
int *d;
*c=x;
*d=y;
return 0;
}
Basically I am trying to create two reference variable (a,b) and assigned with two variables (x,y). after that I created two pointer variable(c,d) and tried to assign same variables (x,y). This gives me error while exection and not at compilation.
whether I am doing any wrong, this is not a standard assignments of pointer variable. why the pointer assignment is getting failed at this point. Please help me to understand this.
1st Update:
Thanks to all. First, I understood that I am working on a C++ feature (reference variable).
Second, I need to allocate memory for the pointer variables before play with it.
The code you posted is C++, not C. And your problem is that you need to make those pointers actually point at something:
int * c = & x; // make c point at x
* c = 42; // changes x
You have declared c and d as int pointers and you are trying to update their pointed values, they aren't pointing to anywhere valid since you never initialize them with valid memory.
Try c = &x; and then play with c.
You are dereferencing an invalid pointer. 'c' and 'd' were not assigned a memory location and so will be using whatever was previously in memory as their location. You need to do:
int *c = new int;
int *d = new int;
It looks to me like you're not entirely clear on the syntax.
Typing int *c is tricky, because it looks like you're declaring an integer with the name *c. However, this is not the case. This will declare a pointer to an integer, and in C/C++, pointers to a certain type are denoted by appending a * after the type name. Thus, you're declaring a variable of type int* (pointer to an integer), with the name c, even though the spacing makes it look different. For the record, typing int* c yields the same result, and is arguably more readable.
It follows then that typing *c does not reference your variable, as it is actually called c. Instead, what this does is dereference the pointer: it returns whatever object the pointer is pointing to. Or, if the pointer is invalid, cause an error.
If you want to declare a pointer and set it to point to an object at a later point, you need to do this:
int *c;
// stuff goes here
c = &x;
&x will return x's address in memory, which can be assigned to a pointer as a value. Then, you can manipulate the value through the pointer by dereferencing it: e.g. *c = 15.
You have defined two pointer variables c and d but you have not allocated any memory for them. You need to assign some memory to both of them.
Do this:
int *c = &x;
int *d = &y;