Creating a pointer within a class to another object - c++

May someone please help me correct the following. I'm trying to wrap my head around how to create a pointer to an existing object within a new object. I can't get the syntax correct and keep getting errors.
Here's my code:
class Country
{
string name;
public:
Country (string name)
{ name = name;
cout << "Country has been created" << endl;}
~Country()
{cout << "Country destroyed \n";}
};
class Person
{
//string name;
//Date dateOfBirth;
Country *pCountry;
public:
Person(Country *c):
pCountry(c)
{}
};
int main()
{
Country US("United States");
Person(&US)
return 0;
}

Did you forget in your main.cpp?
#include <string>
#include <iostream>
using namespace std;
you also need a semicolon in your main:
int main()
{
Country US("United States");
Person person(&US); // < -- variable name and semicolon missing
return 0;
}
You should also change:
Country (string name)
{
this->name = name; // <-- assign name to member variable
...
or better, use member initializer lists:
Country (string name) : name(name) // <-- assign name to member variable
{
...
And in general you should try to be consistent with the way you format your code.

Related

Classes not giving required output in c++

I have created a class name Employee and inside that I have declared a function and two variable(name ,age) . After creating a variable x I am not getting the name insted getting empty name and age =0
CODE:
#include<iostream>
using namespace std;
class Employee{
public:
string name;
int age;
void print(){
cout<<"Name:"<<name<<endl;
cout<<"Age:"<<age<<endl;
}
Employee(string name,int age){
name = name;
age=age;
}
};
int main(){
Employee x=Employee("chang",33);
x.print();
return 0;
}
Expected:
name:Chang
age :33
OutPut:
name:
age :0
Can Someone tell me what is the reason behind it.
Employee(string name, int age) {
name = name;
age = age;
}
you are not modifying the class members, but the parameters instead.
You have three ways to solve this problem:
use this-> to precisely target the right variables.
Employee(string name, int age) {
this->name = name;
this->age = age;
}
use an initialisation list:
Employee(string name, int age) : name(name), age(age) {
}
don't use any constructor, but use brace initialization instead:
int main() {
Employee x = Employee{ "chang", 33 };
x.print();
}
I would personally use option three with the braces, as it's the most efficient to write.
read here why you shouldn't be using namespace std;

How can i access to any data that is in private section of class?

#include <iostream>
#include <vector>
using namespace std;
class Test
{
private:
int ID;
string name;
public:
Test(int ID, string name);
};
Test::Test(int ID, string name)
{
this->ID = ID;
this->name = name;
}
int main()
{
vector<Test *> test_vect;
Test *ptr = new Test(100, "John");
test_vect.push_back(ptr);
cout << ptr->ID << endl;
return 0;
}
This is a simple code I'm trying.
I want to access to the data that I stored in vector.
I thought it would be accessible by using -> just like vector of struct but I can't. So I want to know how to load the data in class.
In addition, I thought sending data to heap section using new would make it accessible at any time I want regardless of whether it is private or public, but it seems like it is not possible.
Can you explain how it works?
(I don't even fully understand how class work, so detailed explanation would be very appreciated. Thx!)
A private variable cannot be accessed by code outside the class definition. (There are exceptions with friend)
ptr->ID does not work because main is outside the class definition.
This can be fixed by using a getter method.
#include <iostream>
#include <vector>
using namespace std;
class Test
{
private:
int _ID;
string _name;
public:
int ID() {return _ID;}
string name() {return _name;}
Test(int param_ID, string param_name);
};
Test::Test(int param_ID, string param_name)
{
_ID = param_ID;
_name = param_name;
}
int main()
{
vector<Test *> test_vect;
Test *ptr = new Test(100, "John");
test_vect.push_back(ptr);
cout << ptr->ID() << endl;
return 0;
}
The above example shows the getter methods ID() and name() which return the data members _ID and _name respectively.
ID() is allowed to access _ID because ID() is part of the class definition. name() is allowed to access _name because name() is part of the class definition.
Note: I would still consider this code to be flawed because it creates a new object on the heap, but does not delete it. You should also look up the keywords new and delete to see how they operate together.

what is the difference between two types of defining constructors? first one using ":" and the second one defining it in curly braces like functions

I have problem in defining constructors for classes and the way I have defined them earlier, doesn't work here properly.
This is for edx c++ intermediate course. when I try to define a class that inherits from some other class, referring to my base class with a constructor doesn't work properly and so my new class won't be defined correctly. What's the difference between the first use of constructors in the first code (using ":" notation that works properly), and the second one in second code (defining like function, that I have used before properly and doesn't work here)?
I have a base class called Person and a Student class that inherits from the base class. When I try to initialize a Student object that calls one of Person class constructors, it gives wrong answers. I think this is because of the way I define constructors. I make them like functions and initialize variables in curl braces. I have used this method earlier and it was working properly, but it doesn't work here. But the standard method using ":" before curly braces works properly here. I want to know what is the difference between these two?
Person.h:
#pragma once
#include <string>
class Person
{
private:
std::string name;
protected:
int age;
public:
Person();
Person(const std::string & name, int age);
void displayNameAge() const;
};
Person.cpp:
#include "pch.h"
#include "Person.h"
#include <iostream>
//Person::Person()
// : name("[unknown name]"), age(0)
//{
// std::cout << "Hello from Person::Person()" << std::endl;
//}
Person::Person()
{
name = "[unknown name]";
age = 0;
std::cout << "Hello from Person::Person()" << std::endl;
}
Person::Person(const std::string & name, int age)
{
this->name = name;
this->age = age;
std::cout << "Hello from Person::Person(string, int)" << std::endl;
}
//Person::Person(const std::string & name, int age)
// : name(name), age(age)
//{
// std::cout << "Hello from Person::Person(string, int)" << std::endl;
//}
void Person::displayNameAge() const
{
std::cout << name << ", " << age << std::endl;
}
Student.h:
#pragma once
#include "Person.h"
class Student : public Person
{
private:
std::string course;
public:
Student();
Student(const std::string & name, int age, const std::string & course);
void displayCourse() const;
};
Student.cpp:
#include "pch.h"
#include "Student.h"
#include <iostream>
Student::Student()
{
course = "[unassigned course]";
std::cout << "Hello from Student::Student()" << std::endl;
}
// first method: the right one
//Student::Student(const std::string & name, int age, const std::string & course)
// : Person(name, age), course(course)
//{
// std::cout << "Hello from Student::Student(string, int, string)" << std::endl;
//}
// second method: the wrong one
Student::Student(const std::string & name, int age, const std::string & course)
{
Person(name, age);
this->course = course;
std::cout << "Hello from Student::Student(string, int, string)" << std::endl;
}
void Student::displayCourse() const
{
std::cout << course << std::endl;
}
Main.cpp:
#include "pch.h"
#include "Student.h"
int main()
{
// Create a Student object using the no-argument constructor.
Student Student1;
Student1.displayNameAge();
Student1.displayCourse();
// Create a Student object using the parameterized constructor.
Student Student2("Jane Smith", 25, "Physics");
Student2.displayNameAge();
Student2.displayCourse();
return 0;
}
expected result:
Hello from Person::Person()
Hello from Student::Student()
[unknown name], 0
[unassigned course]
Hello from Person::Person(string, int)
Hello from Student::Student(string, int, string)
Jane Smith, 25
Physics
actual result:
Hello from Person::Person()
Hello from Student::Student()
[unknown name], 0
[unassigned course]
Hello from Person::Person()
Hello from Person::Person(string, int)
Hello from Student::Student(string, int, string)
[unknown name], 0
Physics
Initializer List
What you are missing is the initializer list.
Type::Type(Parameters)
: member1(init) // This is the initializer list
, member2(init)
{
Your code
}
If you do not explicitly provide one then the compiler will do it for you using the default constructor for the parent class then a call to the default constructor for each member.
So lets look at your class.
Student::Student(const std::string & name, int age, const std::string & course)
{
// Code
}
That is what you wrote. But this is what the compiler implemented.
Student::Student(const std::string & name, int age, const std::string & course)
: Person()
, course()
{
// Code
}
So because you did not do anything the compiler added it calls to the Person default constructor and course (std::string) default constructor.
Now the problem comes if your base class does not have a default constructor. Then the compiler can not add the appropriate calls and will generate a compiler error.
But there is also the issue that the way you are writing this is very inefficient as you are basically initializing all the members twice. Your calling the default constructor then in the Code section you are re-initializing the members with another value.
Student::Student(const std::string & name, int age, const std::string & course)
: Person(name, age)
, course() // Initialize it to empty here.
{
course = "[unassigned course]"; // Re-Initialize it with info.
}
You could simply do it once:
Student::Student()
: Person() // Note person must have a default constructor for this to work.
, course("[unassigned course]")
{}
Temporary Object
Student::Student(const std::string & name, int age, const std::string & course)
{
Person(name, age);
// CODE.
}
This is not doing what you think.
Lets add the initializer list.
Student::Student(const std::string & name, int age, const std::string & course)
: Person()
, course()
{
Person(name, age); // This is creating a person object localy.
// the person object has no name so is a
// temporary variable and goes out of scope
// at the ';'. So it is created and destroyed
// in place before other code is executed.
//
// This does not help initialize the class.
// It is creating a completely different
// and independent object.
// CODE.
}
You can see the execution here:
Hello from Person::Person() // Init parent
Hello from Person::Person(string, int) // Init the temp object.
// If you put a print in the destructor
// You will also see that executed
// Before the Student
// This is also why the object has "unknown name" and 0 age.
Hello from Student::Student(string, int, string) // Now we init the student
[unknown name], 0
Physics
Advice
Is there a valid scenario where you want initialized versions of the object? Personally I think not (if there are then ignore this) so get rid of the default constructors of Person and Student. Then you can not create uninitialized Students or `People.

What is wrong? - Composition compile error (with family+person classes example)

I got two classes, one named Person that I checked is working (I can create objects of that class so the problem should not be here).
I then have another class called Family with composition from Person:
Family.h
#include "Person.h"
class Family
{
public:
Family();
void printFamily();
private:
Person dad_();
Person mum_();
Person son_();
Person daughter_();
};
Family.cpp
#include "Family.h"
Family::Family()
{
}
void printFamily()
{
dad_.printAll();
mum_.printAll();
son_.printAll();
daughter_.printAll();
//printAll() is a function in the Person class that worked when
//I tested it earlier with only the person class
}
But when i try to compile this I get an error:
left of '.printAll' must have class/struct/union
'son_' : undeclared identifier
This error goes for all the .printAll() calls in family.cpp.
I can't see why this wouldn't work, so I hope you can.
Edit1:
Ok i changed
void printFamily()
to
void Family::printFamily()
That removes one error, but i still get
left of '.printAll' must have class/struct/union
Edit2
Ah my bad with the Person calls i changed them to
Person dad_;
and the same with the rest.
Seems like their might be an error with my Person class so i will post that also
Person.h
#include <string>
using namespace std;
class Person
{
public:
Person( const string & = "000000-0000", const string & = "N", const string & = "",const string & = "N");
~Person();
void setFirstName(const string &);
void setMiddleName(const string &);
void setLastName(const string &);
void getData(string &,string &,string &,string &);
static int getNumberOfPersons();
void printPartially() const;
void printAll() const;
bool checkForSameName(const Person &);
private:
string firstName_;
string middleName_;
string lastName_;
string socialSecNumber_;
static int numberOfPersons_;
};
Person.cpp
#include "Person.h"
#include <iostream>
int Person::numberOfPersons_ = 0;
Person::Person( const string &sNumber, const string &firstName, const string &middleName,const string &lastName )
:firstName_(firstName),middleName_(middleName),lastName_(lastName),socialSecNumber_(sNumber)
{
numberOfPersons_ ++;
}
Person::~Person()
{
numberOfPersons_--;
}
void Person::setFirstName(const string &firstName)
{ firstName_ = firstName; }
void Person::setMiddleName(const string &middleName)
{ middleName_ = middleName; }
void Person::setLastName(const string &lastName)
{lastName_ = lastName;}
void Person::getData(string &fName,string &mName,string &lName,string &sNumber)
{
fName = firstName_;
mName = middleName_;
lName = lastName_;
sNumber = socialSecNumber_;
}
int Person::getNumberOfPersons()
{
return numberOfPersons_;
}
void Person::printPartially() const
{
cout <<"Navn: "<<firstName_<<" "<<middleName_<<" "<<lastName_<<endl;
cout <<"Født: ";
for (int i = 0;i<6;i++)
{
cout <<socialSecNumber_.at(i);
}
}
void Person::printAll() const
{
cout <<"Navn: "<<firstName_<<" "<<middleName_<<" "<<lastName_<<endl;
cout <<"Personnr: "<<socialSecNumber_<<endl;
}
bool Person::checkForSameName(const Person &p)
{
if (p.firstName_ == firstName_ && p.middleName_ ==middleName_ && p.lastName_ == lastName_)
return true;
else
return false;
}
Now i am getting some new errors:
error C2011: 'Person' : 'class' type redefinition
see declaration of 'Person'
'Family::dad_' uses undefined class 'Person'
The "dad" error applies to the whole family
You have a few syntax issues.
First, you're declaring each of what are supposed to be member variables as functions which return Person. They should look like (note, no parens):
Person dad_;
Person mum_;
Person son_;
Person daughter_;
You're also missing the scoping on your definition of printFamily:
void Family::printFamily() {
...
}
Without the preceding Family::, C++ thinks you're defining a free function, and doesn't know to look inside the Family class for the declarations of dad_, mum_, etc.
Additionally, at least with the code you've shown, there's no way to initialize the people in your class. The Family constructor should take arguments to define the people, or you should have setters which allow defining them later. Right now, you'll get 4 identical people, set up however the default person constructor builds them.
I would normally prefer the constructor method, but I have other design reservations about your code to begin with (e.g. Does a family always contain mum, dad, brother, sister?) and that's not really what this question is about.
The line:
Person dad_();
says that dad_ is a function that returns a Person, not an object. Did you mean that? Similarly for others.
Try
Person dad_;
Family.h
#include "Person.h"
class Family
{
public:
Family();
void printFamily();
private:
Person dad_;
Person mum_;
Person son_;
Person daughter_;
};
Family.cpp
#include "Family.h"
Family::Family()
{
}
void Family::printFamily()
{
dad_.printAll();
mum_.printAll();
son_.printAll();
daughter_.printAll();
//printAll() is a function in the Person class that worked when
//I tested it earlier with only the person class
}
The out of line definition of a member function needs to include the class name:
void Family::printFamily()
{
//...
Surprisingly, you already got this right for the constructor but then immediately forgot...
Second, your private class members are functions, not data members (which is odd), but if that's deliberate, you need to call them:
dad_().printAll();
// ^^^

need help with object oriented program in Visual C++

guys, I have the following code, but I'm getting error at compiling time... the error is at the end. Thanks
1st Class is "Person"
#ifndef PERSON_H//protecting .h files
#define PERSON_H//protecting .h files
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
Person();
Person(string first, string last)
{
firstName = first;
lastName = last;
}
virtual void setName(string first, string last)
{
firstName = first;
lastName = last;
}
virtual void setWeightAge(int w, int a)
{
weight = w;
age = a;
}
virtual string getFirstName()
{
return firstName;
}
virtual string getLastName()
{
return lastName;
}
virtual int getWeight()
{
return weight;
}
virtual int getAge()
{
return age;
}
virtual void printPerson()
{
cout << "Name: " << firstName << " " << lastName << endl;
cout << "Age: " << age << endl;
cout << "Weight: " << weight << endl;
}
protected:
string firstName, lastName;
int weight, age;
};
#endif
2nd Class is "Student"
#ifndef STUDENT_H//protecting .h files
#define STUDENT_H//protecting .h files
#include <iostream>
#include <string>
#include "Person.h"
using namespace std;
class Student : public Person
{
public:
Student();
Student(Person s)
{
sStudent = s;
}
virtual void setGPA(double g)
{
gpa = g;
}
virtual void setSchedule(string c, string t, string d)
{
stClass = c;
time = time;
days = d;
}
virtual void setGrade(char g)
{
grade = g;
}
virtual double getGPA()
{
if (grade == 'a') { gpa = 4.0; }
if (grade == 'b') { gpa = 3.0; }
if (grade == 'c') { gpa = 2.0; }
else gpa = 0;
return gpa;
}
virtual char getGrade()
{
return grade;
}
virtual void printSchedule()
{
cout << "Class | Days | Time " << endl;
cout << stClass << " | " << days << " | " << time << endl;
}
protected:
string stClass, time, days;
char grade;
double gpa;
Person sStudent;
};
#endif
and Main()
#include <iostream>
#include "Student.h"
using namespace std;
int main()
{
//creating a person
Person john("John", "Smith");
john.setWeightAge(180, 39);
john.printPerson();
//making john a student
Student johnStdntMath(john);
johnStdntMath.setSchedule("Math", "7:45", "M, W");
johnStdntMath.setGrade('b');
johnStdntMath.printPerson();
johnStdntMath.printSchedule();
system("pause");
return 0;
errors:
1>------ Build started: Project: Person, Configuration: Debug Win32 ------
1> main.cpp
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Person::Person(void)" (??0Person##QAE#XZ) referenced in function "public: __thiscall Student::Student(class Person)" (??0Student##QAE#VPerson###Z)
1>c:\users\jorge\documents\visual studio 2010\Projects\Person\Debug\Person.exe : fatal error LNK1120: 1 unresolved externals
}
I suggest you double check your is-A and has-A relationships.
Writing Student : public Person says that a Student is-A Person. But later, you have a member variable sStudent of type Person, which says a Student has-A Person, and I'm guessing is not what you really want.
Check out the answers to this question: Inheritance vs. Aggregation for better explanations.
Listen to your linker, it's just as it says: In constructor Student::Student(Person) you're referring to constructor Person::Person(), but you didn't define Person::Person(), not in a way the linker can see when it does its thing with the Student constructor.
Technically, because you are filling in sStudent in the Student constructor's body the compiler first default-initializes the Person object sStudent, and then assigns to it s, the Person parameter of the constructor. If you'd use the initializer list then the Person member wouldn't be default-initialized and then assigned to but rather copy-constructed right away:
Student(const Person& s) : sStudent(s) { }
But the question remains: Why are you publicly declaring a default constructor in Person and not define it?
Also, you have a leak in Student. The string and Person members of Student won't clean up because when a Student object destructs its destructor won't be called. The Person destructor will be called, but not the Student destructor, and the reason being that the destructor of Person is non-virtual.
One more thing: It's a bad idea in object-oriented design in general and C++ in particular to use inheritance for reuse. The reason is that this very often leads to a violation of the LSP. It can also bear a (not major but nonetheless) performance overhead for introducing a virtual table. But it's the correctness that suffers that matters when you pick inheritance when you should really be using delegation.
You are accessing the no argument constructor for Person when you create the johnStdntMath instance. You need to either
Implement Person::Person() or ...
Change Student::Student(Person s) to Student::Student(Person const& s)
There are some other problems in your code as well. Student is-a Person so there is no need for the Student class to have a Person member variable - it shares the instance variables of its base class by virtue of inheritance. In other words, Student extends Person so your program could be written:
int main() {
Student johnStdntMath;
johnStdntMath.setName("John", "Smith")
johnStdntMath.setWeightAge(180, 39);
johnStdntMath.setSchedule("Math", "7:45", "M, W");
johnStdntMath.setGrade('b');
johnStdntMath.printPerson();
johnStdntMath.printSchedule();
return 0;
}
I would also avoid the using namespace std; statement anywhere and especially in a header file. For example, your Student class contains a member variable named time. This will conflict with the std::time_t std::time(std::time_t*) function defined in <ctime> if that header is included before "student.h".
You haven't implement the default constructor Person(),you can write it like this:
Person():weight(0)
,age(0){};
If you just want to complier it, this is enough;
Here are some tips below:
1.Check your mind, does class Student really need a Person member. If you really need it, Student(Person) may add an explicit symbol:
explicit Student(const Person& s) : sStudent(s) {...};
2.In Person.h
protected:
string firstName, lastName;
int weight, age;
the protected may be private?