I am learning C++ and i currently have some questions that i don't know the answers. I create this header file Object1.h and can compile this file but when i run the Test.cpp, Visual Studio throw an error because of access violation by *sibling. The strange thing is I can run it using Dev C+ and it return only value 2.Therefore I want to ask why assigning *sibling will create an error and why i can't change Person B's address using setAddress(). I will really appreciate if any one can give me some answer or hints. Thanks in advance.
//This is Object1.h
#include <iostream>
using namespace std;
class Person{
public:
Person(int ID);
void setAddress(string addr);
string getAddress();
void addSibling(Person *p);
Person getSibling();
int ID;
private:
string address;
Person *sibling;
};
Person::Person(int ID){
this->ID = ID;
}
void Person::setAddress(string addr){
this->address = addr;
}
string Person::getAddress(){
return address;
}
void Person::addSibling(Person *p){
*sibling = *p;
}
Person Person::getSibling(){
return *sibling;
}
//This is Test.cpp
#include <iostream>
#include <string>
#include "Object1.h"
using namespace std;
int main(){
Person A(1);
Person B(2);
A.addSibling(&B);
// Change the address of person B through person A's getSibling()
A.getSibling().setAddress("123 Street");
cout << B.getAddress() <<endl;
cout << B.ID;
system("Pause");
return 0;
}
Using operator * assumes that you deal with some data resided by address stored in this variable. Let's review your code:
*sibling = *p;
You trying to copy by value. This is wrong because sibling points to nowhere. It is even not a NULL, it is unpredictable. The correct line will be:
sibling = p;
So you tell that would store pointer to another instance.
One notable problem is that you're returning by value in getSibling(), so you'll get a copy of the sibling rather than that actual sibling. Any changes you make will be to the temporary object.
As others have noted, you're addSibling function should be sibling = p. That's the source of your error.
But be sure to correct your getSibling function otherwise your setAddress won't do what you want.
Related
I am learning c++ from 'Teach yourself c++ in 21 days' by Liberty and Jones. Compiler I am using is gcc 6.3.0. I am on pointer topic. First I am writing one code similar to the one book gives which works fine. Here it is:
#include <iostream>
using namespace std;
class Cat
{
public:
Cat();
int Getage() {return *itsage;}
private:
int *itsage;
};
Cat::Cat()
{
itsage=new int;
*itsage=2;
}
int main()
{
Cat *Mani=new Cat;
cout << "Mani is a cat whose age is: " << Mani->Getage();
cout << endl;
return 0;
}
Output: Mani is a cat whose age is: 2
Now instead of using constructor, I thought of using accessor function to set age. I wrote the following code which gave me output as above but I have doubt why this code work. Here is the code I wrote.
#include <iostream>
using namespace std;
class Cat
{
public:
void Setage(int age) {*itsage=age;}
int Getage() {return *itsage;}
private:
int *itsage;
};
int main()
{
Cat *Mani=new Cat;
Mani->Setage(2);
cout << "Mani is a cat whose age is: " << Mani->Getage();
cout << endl;
return 0;
}
Doubt: What I studied so far tells me that whenever pointer declared, it should get initialized, i.e. we should assign some memory address to it. In the first code, we are initializing our pointer member variable in the constructor by this command itsage=new int; which looks fine. But in the second code, I nowhere assigned any memory address to pointer itsage. But still code worked fine. I am little confused here.
I have one more doubt(I am asking here itself as it is related to the above code. If it's bad, I will ask it in different question.) I thought of making pointer itsage in the above code public. But I don't know how can I access it. I tried the following but didn't work.
#include <iostream>
using namespace std;
class Cat
{
public:
int *itsage;
};
int main()
{
Cat *Mani=new Cat;
Mani->*itsage=2;
cout << "Frisky's age is " << Mani->*itsage;
return 0;
}
So how to access public pointer member variable of object created on heap?
Thanks.
About your first question. I was confused at first, this is a neat answer, which shows that the compiler did it for you.
About your second question, it's nothing but an improper way of accessing the pointer. You should realize that when trying to access the content of a pointer, you must get its address then go to its content. So you need to:
Get its address: Mani -> itsage
Access its content: *(Mani -> itsage)
In this function:
void Setage(int age) { *itsage=age; }
you are dereferencing itsage, but it's not pointing to valid memory. This invokes undefined behavior. You need to do:
void Setage(int age) {
itsage = new int;
*itsage=age;
}
For the second question, the correct syntax to access a member variable of pointer type is:
*(Mani->itsage) = 2;
Note that this is undefined behavior too, for the same reason as above. The fix is also the same; you need to do:
Mani->itsage = new int;
*(Mani->itsage) = 2;
But in the second code, I nowhere assigned any memory address to pointer itsage. But still code worked fine. I am little confused here.
That's a fair doubt. In fact, your 2nd code should never work, as no memory had ever been allocated to itsage. If it still somehow "worked" for you then it is still a typical undefined behaviour.
You should still allocate the memory before usage as usual, and free it in the constructor. As your class doesn't even have a destructor, perhaps you should choose unique_ptr instead:
class Cat
{
public:
void Setage(int age) { itsage = make_unique<int>(age); }
int Getage() { return *itsage; }
private:
unique_ptr<int> itsage;
};
So i need to get code of the structure#1 (e[0]) but i get the following error;
"error: request for member 'get_code' in 'emp1', which is of pointer type 'Employee*' (maybe you meant to use '->' ?)"
i don't really understand how to fix this. Plus, it's an assigment so i'm bound to use structures,and also, i don't know what "->" is, but if it's any operator or something, im not allowed to use it cause we haven't been taught that yet.
(Answers to the similar question suggest using -> so that doesnt work for me.)
i also tried using *(emp1).get_code()
#include <iostream>
#include <string.h>
using namespace std;
struct Employee{
private:
string code;
string name;
float salary;
public:
void set_code(string c){
code=c;
}
void set_name(string n){
name=n;
}
void set_sal(float s){
salary=s;
}
string get_code(){
return code;
}
string get_name(){
return name;
}
float get_sal(){
return salary;
}
};
int main(void) {
Employee e[2],*emp1,*emp2;
string c,n;
float s;
for (int i=0;i<2;i++){
cout<<"Enter code for employee "<<i+1;
cin>>c;
e[i].set_code(c);
cout<<"Enter name for employee "<<i+1;
cin>>n;
e[i].set_name(n);
cout<<"Enter salary for employee "<<i+1;
cin>>s;
e[i].set_sal(s);
}
*emp1=e[0];
cout<<emp1.get_code();
}
First of all, this line is not correct:
*emp1=e[0];
What your line does is assign the structure value 'e[0]' to the structure at pointer 'emp1'. However, the pointer 'emp1' is never initialized, so you'd end up writing in an invalid location.
What you need to write is:
emp1=&e[0];
That will actually set emp1 to the location of 'e[0]'.
Secondly, the symbol '->' is what you use when you want to access a member of a pointer.
In this case you should not write:
cout<<emp1.get_code();
But rather:
cout<<emp1->get_code();
The reason why you need to write that is that 'emp1' is a pointer. Thus, to access its member 'get_code', you need to use the symbol '->'.
As you can see I am new to C++, but I can't understand why y = new Person() in function foo is wrong. Thanks for your help.
I get the this error:
error: no match for ‘operator=’ in ‘y = (((Person*)operator new(32u)),
(, ))’
UPDATE:
I will accept the answer with the most upvotes by tonight or the one that is more convincing.
The argument between me and my friend is wether the function foo can change the object and propagate the change outside the function like when doing y = Person(), then also brother will change or will it remain intact?
.
CODE:
#include <iostream>
using namespace std;
class Person {
public:
int age;
char name[25];
Person() {
age = 0;
}
};
void foo(Person &y)
{
y = new Person();
}
int main()
{
Person *brother = new Person();
brother->age = 20;
cout << "age = " << brother->age << endl;
foo(*brother);
cout << "age = " << brother->age << endl;
return 0;
}
You probably come from a language were objects can only be created with new. In C++, this is not the case. And unless you really need it, you should not use new. Just create it as a normal variable:
#include <iostream>
#include <string>
class Person
{
public:
unsigned age;
std::string name;
Person(unsigned age, std::string name)
: age(age)
, name(std::move(name)) // move is C++11
{}
};
int main()
{
Person brother(8, "Tim John");
std::cout << "age = " << brother.age << '\n';
// Edit regarding the question in the comments:
brother = Person(16, "John Tim");
std::cout << "age = " << brother.age << '\n';
}
Your problem with the code above is that new returns a Pointer, and you are trying to assign a pointer to a Person, which obviously can't work.
void foo(Person &y)
{
y = new Person();
}
y is a reference, not a pointer. To reassign to y, you'd use
y = Person();
but if you really want to allocate a new person, you'd use
void foo(Person* &y) // reference to pointer to Person
With a reference, you basically say that you modify the value at the calling site.
Note that your current code leak. If you have a bare pointer that you want to manage yourself, you have to delete it first:
void foo (Person*& y)
{
delete y;
y = new Person;
}
But as you see, the code is already becoming messy without knowing your target. It might be more appropriate to delete at the calling site, or to not allocate y at all before calling foo(...).
Also note that using foo (Person* y) instead would not solve the issue of newing at the calling site:
void foo (Person *y)
{
y = new Person();
}
This of course compiles, but modifies only foo's own y variable. The caller will have an unchanged pointer.
Note that you'd better use value types or smart pointers, as it is non-trivial to write exception safe code that manually manages memory.
In function foo the line should be
y = Person();
y is not a pointer.
EDIT: actually, this is the wrong answer (even though you're currently accepted it from Jon). You are not supposed to mix heap and stack, and cause memory leaks like that. The right way to do it is to change members of the object directly. Assignment operator (operator=) will change the members of the object. Because the question is not about mixing heap and stack, but about changing object here's the code that better explains the problem. Note that there's no new here to complicate the issue.
void foo(Person &y)
{
y = Person();
}
int main()
{
Person brother;
brother.age = 20;
...
foo(brother);
...
return 0;
}
After y = Person() the brother object will be changed because y is brother and assignment operator changes the members of the object.
Never confuse yourself with the & and * operators when dealing with pointer operations.
'&' is used in different context.
&, when used in a function's formal parameters is a reference parameter , this operator passes a variable by reference(by its address).However the variable y still acts like a normal variable.
So this block of code..
void foo(Person &y)
{
y = new Person();
}
would not work as new Person() is parsing a pointer to a variable.
For example,
int * intp = new int;
int variable = intp;
this is the type of thing that's happening here.A reference parameter acts like a variable but actually has direct access to the variable due to the fact that it's a call by referance operation.
The correct way to write this function will look like this
void foo(Person ** y)
{
*y = new Person();
}
That is if you're trying to initialize a class pointer via a function.
As cooky said this is a misconception people make in c++ whom program in languages that require the new keywork in order to create an object/variable.
SOURCES
http://fredosaurus.com/notes-cpp/functions/refparams.html
you are tryng to call the "new" operator on a reference. while the "new" is used only with pointers.
pass to void foo( ) function
Person*
instead of
Person&
A little explanation :
The right way to pass a parameter depends on what you have to do!!
If you want to do side effects to the object passed to the function the right way is to declare :
void foo(Person& person)
the object person can be modified..
if you don t waant to do side effects to the object you have to declare the object 'const':
void foo(const Person& person)
the const means you cannot modify the object inside your method even if you are passing a reference..
then you can pass a pointer:
void foo(Person* person)
here you can modify the object that "person" is pointing at, but you have a copy of the original pointer.
last way to pass parameters is :
void foo(Person*& person)
here you have an alias of the original pointer. alias means "the same pointer with a different name"
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class newclass
{
public:
string *Date;
void show(){ cout << this->Date;}
};
int main()
{
newclass *n = new newclass;
n->Date = new string ;
n->Date.assign("hello"); // get an error on this line
n->show();
return 0;
}
Can Somebody please explain me how this works?. I am new to this.
n->Date->assign("hello") because n->Date is a pointer, so you must dereference it before calling a function on it.
Please look at this SO Question for a detailed explanation of the syntax.
It looks like you're applying idioms from another language. In C++ you should avoid pointers whenever possible, replaced by member or local variables. Your code in that case would look like this:
class newclass
{
public:
string Date;
void show(){ cout << this->Date;}
};
int main() {
newclass n;
n.Date.assign("hello");
n.show();
return 0;
}
You've got a few problems here, let's go over them one at a time:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class newclass
{
public:
// This is a pointer to a std::string, that doesn't appear to
// be allocated. From this small example, you don't really need
// a pointer at all:
// string *Date;
// now that this object isn't a pointer, you can use dot syntax
// to access its member functions
string Date;
void show()
{
// accessing date through this-> is not necessary
// here. You can simply use Date. However since this
// doesn't cause any specific problems I mention it only
// as informational
cout << this->Date;
}
};
int main()
{
newclass *n = new newclass;
// This is bad practice, you generally shouldn't be allocating
// objects within a class outside of that class's implementation.
// this would better be done in the newclass constructor.
// n->Date = new string ;
// Since we replaced the pointer to string object Date in newclass
// and replaced it with an automatic string object, this line will
// now work as written.
n->Date.assign("hello"); // get an error on this line
n->show();
// At this point your program will exit, and newclass is shown as
// a memory leak. While the OS will reclaim this memory at application
// exit, its good to get used to managing the lifetime of your objects
// appropriate. This has do be deleted, or better yet wrapped in a smart
// pointer
delete n;
return 0;
}
To provide an example that is similar to your original question, let's take the following code:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <memory>
using namespace std;
class newclass
{
public:
// auto_ptr is a smart pointer class that
// wraps a dynamically allocated object and
// provides cleanup for it when it goes out
// of scope. So when our class goes out of
// scope the Date object will be cleaned up
// for us
auto_ptr<string> Date;
// this is the constructor of the newclass object
// its called anytime a newclass object is instantiated
// we use the initializer list to allocate the Date object
newclass() : Date(new string)
{
}
// a mutator for setting the Date object (promotes encapsulation)
void set_date(const std::string& val)
{
// necessary to dereference to get at the date object
(*Date) = val;
}
void show() { cout << this->Date; }
};
int main()
{
// note the use of an auto_ptr here for automatic cleanup
auto_ptr<newclass> n(new newclass);
// use our mutator method to set the date
n->set_date("hello");
n->show();
return 0;
}
Date is itself a pointer to string, you will need to dereference it as well:
n->Date->assign("hello");
newclass *n = new newclass;
n->Date = new string ;
n->Date->assign("hello"); // use -> when accessing a member of a pointer
n->show();
I have been a follower for a long time but this is the first time I ask a question. In a nutshell, the issue is; vector<Student*> studentvector that is a vector of object pointers seems to push the student info back as student ; but when I print to see the first one in vector whether it performs as intended, I see it always updates the first record with new coming student info although there is no problem on studentvector.size() It pushes the record back to the vector as many as how many time I call addStudent(...) but it fills all vector with the information of last student. What may be done to succeed in filling vector with correct info within this frame, without using smart pointers or advanced stuff?
Sorry if I am vague on my question. You may lead me to provide what is also necessary to understand the problem. Thanks in advance.
addStudent(const string alias, const string name) throw(StudentException)
{
Student* student = new Student(alias, name)
studentvector.push_back(student);
cout << studentvector.front() << endl;
}
That is the implementation of Student;
#include "Student.h"
string *Alias;
string *Name;
Student::Student(string alias)
{
Alias = new string(alias);
}
Student::Student(string alias, string name)
{
Alias = new string(alias);
Name = new string(name);
}
Student::~Student()
{
delete Alias;
delete Name;
}
const string& Student::getAlias() const
{
return *Alias;
}
void Student::setAlias(const string& alias)
{
*Alias = alias;
}
const string& Student::getName() const
{
return *Name;
}
void Student::setName(const string& name)
{
*Name = name;
}
Consider alias is not reserved.
Doh! Here's your problem - all objects from type Student use the same global pointers:
string *Alias;
string *Name;
Make these two as members in you class
class Student
{
private:
string *Alias;
string *Name;
//..
};
EDIT:
Also, I don't think, that it's a good idea to use pointer to std::string, I'd suggest you to use like this:
class Student
{
private:
string Alias;
string Name;
//..
};
Your Student.cpp defines a single global pointer Alias and a single pointer Name. What you really want is a separate Alias and Name for each Student object. You do this by adding members to the class:
class Student {
public:
Student(const std::string& a, const std::string& n);
//...
private:
std::string Alias;
std::string Name;
};
Student::Student(const std::string& a, const std::string& n)
: Alias(a), Name(n)
{}
I may be delirious here, but are you not specifically printing out front, while pushing back?
studentvector.push_back(student);
cout << studentvector.front() << endl;
You're pushing onto the back, not the front, then printing what's in front. Of course you're not seeing front changing. You need to print back or push front. If push front isn't available, you can use insert(container.begin(), object).
You also need to move those global string variables into the class as members, so that for each instance of Student, the student has instances of Name and Alias.
Another note... you're dynamically allocating a string class. The purpose of the string class is to handle the dynamic memory of a char* string for you. There's no reason for you to use string*s in this situation, as far as I can tell from your code. string will handle the new and delete internally for you.
I agree with what everyone else has said. However, I can't reproduce the problem you say you're having. In particular, the following (rather icky) code correctly outputs two lines saying "Student(foo,bar)".
#include <iostream>
#include <vector>
#include <string>
// NOTE WELL: many things in this code are bad style and should not be imitated.
// One of them is the namespace-polluting using-directive below:
using namespace std;
struct Student {
string alias, name;
Student(string a, string n) : alias(a), name(n) {}
};
class StudentException : public exception {};
vector<Student*> studentvector;
ostream& operator<<(ostream& stream, Student* student) {
stream << "Student(" << student->alias << "," << student->name << ")";
return stream;
}
void addStudent(const string alias, const string name) throw(StudentException)
{
Student* student = new Student(alias, name);
studentvector.push_back(student);
cout << studentvector.front() << endl;
}
int main(void) {
addStudent("foo","bar");
addStudent("baz","quux");
}
It might be helpful to know how your (not-working) code diverges from the above.
A couple of remarks that conceivably might be relevant:
You aren't by any chance confusing the front and back ends of the vector somehow?
If (unlike your addStudent function) your actual code has a single Student object, and is modifying it and then pushing a pointer to it onto your vector, then of course you'll get the kind of wrong results you describe, because it'll be the same pointer every time.
std::vector::front() will return you the reference to the first element in the vector.
If you want to remove element, you need to call pop_back() which will return the element and remove from the vector.
If you have Boost then check out Boost Pointer Containers.