Pointer tho another Object - c++

I have a little problem .. I want to do car registration and i want to have owner(pointer to a Person object) but when i want to take the owner with get function i can't do that ... and this is mystery for me ... Maybe i have a little mistake somewhere and i can't find it .. Please help :)
class Person
{
friend class Cars;
public:
Person(){}
Person(uint8_t age, string name) :m_age(age), m_name(name)
{
m_idGener = s_idGenerator++;
}
int getId()
{
return m_idGener;
}
uint8_t getAge()
{
return m_age;
}
string getName()
{
return m_name;
}
private:
string m_name;
uint8_t m_age;
static int s_idGenerator;
int m_idGener;
};
class Cars:public Person
{
public:
Person *m_owner; // this is my pointer which i want to point to cars Object
it will stay public for the test after the test i will move it in the private section
Cars()
{
}
// getters and setters
Cars setOwner(Cars &object, Person &owner) // with this function i set the owner
{
object.m_owner = &owner;
}
Cars getOwner(Cars &object) /// here is my problem i can't take the owner
{
return *(object.m_owner); // but i can't take the owner
}
uint16_t getHorsePower()
{
return horsePower;
}
string getRegNumber()
{
return registrationNumber;
}
private:
string m_manufacturerName;
string modelName;
uint16_t horsePower;
string registrationNumber;
};
int Person::s_idGenerator = 0;

You have made more mistakes. At least the followings should be corrected:
Cars setOwner(Cars &object, .....
This method doest not return a value, so it should be void. The car object should be the object for which the method will be called, not a parameter.
Cars getOwner(Cars &object) /// here is my problem i can't take the owner
{
return *(object.m_owner); // but i can't take the owner
}
In this method I would change the return type to Person *, then return simply m_owner. Parameter is not needed.
A modified working example:
#include <string>
#include <iostream>
using namespace std;
class Person
{
friend class Cars;
public:
Person(){}
Person(uint8_t age, string name) :m_age(age), m_name(name)
{
m_idGener = s_idGenerator++;
}
int getId()
{
return m_idGener;
}
uint8_t getAge()
{
return m_age;
}
string getName()
{
return m_name;
}
private:
string m_name;
uint8_t m_age;
static int s_idGenerator;
int m_idGener;
};
class Cars:public Person
{
public:
Person *m_owner; // this is my pointer which i want to point to cars Object
// it will stay public for the test after the test i will move it in the private section
Cars()
{
}
// getters and setters
void setOwner(Person &owner) // with this function i set the owner
{
m_owner = &owner;
}
Person *getOwner() /// here is my problem i can't take the owner
{
return (m_owner); // but i can't take the owner
}
uint16_t getHorsePower()
{
return horsePower;
}
string getRegNumber()
{
return registrationNumber;
}
private:
string m_manufacturerName;
string modelName;
uint16_t horsePower;
string registrationNumber;
};
int Person::s_idGenerator = 0;
int main() {
Person p(5,"Bill");
Cars c;
c.setOwner(p);
cout << c.getOwner()->getName();
}

Here:
Cars setOwner(Cars &object, Person &owner) // with this function i set the owner
{
object.m_owner = &owner;
}
You declared out value type as "Cars" but you don't return anything.
And here:
Cars getOwner(Cars &object) /// here is my problem i can't take the owner
{
return *(object.m_owner); // but i can't take the owner
}
You want to return "Person" object but again you declared out value type as "Cars".
So you can change this functions like that:
First:
void setOwner(Cars &object, Person &owner);
Second:
Person getOwner(Cars &object);

Related

How to make a data member of a class unique for each instance of that class

This is the code of the program I have written and everything works just perfectly except the part that it has only one requirement. The ID data member of the class Department should be unique for each instance of that class. I have tried using operator overloading to compare the IDs of the Departments created. But the problem with that would be that the comparison should be made in the main driver of the program, and it is required to be made either in the constructor of the class or inside the class.
Here is the code
class Department {
public:
Department(string id) {
ID = id;
}
bool operator== (const Department& rhs) {
return ID == rhs.ID;
}
friend ostream& operator<<(ostream& out, const Department& value);
protected:
string ID;
};
ostream& operator<<(ostream& out, const Department& value)
{
out << value.ID;
return out;
}
int main() {
Department d1("ID-1");
Department d2("ID-1");
if (d1 == d2) {
cout << "They are the same";
}
else {
cout << "No the same";
}
}
You can make a static attribute that is incremented after each assignment. The static attribute will be the same for all instances.
This may be what the previous answer is intending, though this one increments whenever an object is constructed. That way each object is given essentially a new serial number when it comes to life.
class Department {
public:
Department() {
ID = "ID_" + std::to_string(IDcount);
++IDcount;
}
bool operator== (const Department& rhs) {
return ID == rhs.ID;
}
protected:
string ID;
static int IDcount;
};
int Department::IDcount = 0;
To ensure that no two instances of a class have the same value for a data-member, you can make its constructor non-public and use a singleton friend class to manage its instances.
class Department
{
protected:
string ID;
friend class DepartmentCreator;
Department(string id)
{
ID = id;
}
Department();
};
class DepartmentCreator
{
private:
map<string, Department *> dept_instances;
static DepartmentCreator *this_instance;
DepartmentCreator();
public:
DepartmentCreator(const DepartmentCreator &) = delete;
void operator=(const DepartmentCreator &) = delete;
static DepartmentCreator *GetCreator();
Department *GetDepartment(string id);
};
DepartmentCreator *DepartmentCreator::this_instance = nullptr;
DepartmentCreator::DepartmentCreator() {}
DepartmentCreator *DepartmentCreator::GetCreator()
{
if (!this_instance)
{
this_instance = new DepartmentCreator();
}
return this_instance;
}
Department *DepartmentCreator::GetDepartment(string id)
{
if (dept_instances.find(id) == dept_instances.end())
{
dept_instances[id] = new Department(id);
}
return dept_instances[id];
}
Now, you can use it like this:
DepartmentCreator *dept_creator = DepartmentCreator::GetCreator();
Department *d1 = dept_creator->GetDepartment("ID-1");
Department *d2 = dept_creator->GetDepartment("ID-1");
There is no need to overload ==. You will always get the same pointer for a given ID.

Accessing member in nested composition in C++

If I have a class that contains another class (through composition) which in turn, contains another class. For example: a Teacher class containing a PersonalDetails class, that contains a ContactInformation class.
ContactInformation class:
class ContactInformation
{
private:
std::string m_email{};
std::string m_phoneNumber{};
public:
ContactInformation(const std::string &email, const std::string &phone)
: m_email{ email }, m_phoneNumber{ phone }
{
}
// Solution 1
const std::string& getEmail() const { return m_email; }
const std::string& getPhoneNumber() const { return m_phoneNumber; }
// Solution 2
const ContactInformation& getContactInfo() const { return *this; }
// Solution 3
friend class Teacher;
};
PeronalDetails class:
class PersonalDetails
{
private:
ContactInformation m_contact;
std::string m_name;
public:
PersonalDetails(const ContactInformation &info, const std::string &name)
: m_contact{ info }, m_name{ name }
{
}
// Solution 1
const std::string& getEmail() const { return m_contact.getEmail(); }
const std::string& getPhoneNumber() const { return m_contact.getPhoneNumber(); }
const std::string& getName() const { return m_name; }
// Solution 2
const ContactInformation& getContactInfo() const { return m_contact.getContactInfo(); }
const PersonalDetails& getPersonalDetails() const { return *this; }
// Solution 3
friend class Teacher;
};
Teacher class:
class Teacher
{
private:
PersonalDetails m_details;
double m_salary{};
public:
Teacher(const PersonalDetails &details, double salary)
: m_details{ details }, m_salary{ salary }
{
}
// Solution 1
const std::string& getEmail() const { return m_details.getEmail(); }
const std::string& getPhoneNumber() const { return m_details.getPhoneNumber(); }
const std::string& getName() const { return m_details.getName(); }
double getSalary() const { return m_salary; }
void printEmail1() const
{
std::cout << getEmail() << '\n';
}
// Solution 2
const ContactInformation& getContactInfo() const { return m_details.getContactInfo(); }
const PersonalDetails& getPersonalDetails() const { return m_details.getPersonalDetails(); }
void printEmail2() const
{
std::cout << getContactInfo().getEmail() << '\n';
}
// Solution 3
const std::string& getTeacherEmail(const ContactInformation &c) const
{
return c.getEmail();
}
void printEmail3() const
{
std::cout << getTeacherEmail(getContactInformation());
}
};
What is the "proper way" for the Teacher class to access the members (m_email & m_phoneNumber) in ContactInformation (the most "nested" class)?
Neither of the solutions I can come up with seem all that great.
Solution 1; is to have getters methods for the member variables in all of the classes. But this seems like a bad idea since the Teacher class will end up with a lot of getters methods. Especially if I were to add more classes in the future.
Solution 2; is to return the instance itself. I don't know if this is better or if it breaks any best practices. But you can use the instance in the Teacher class to call getEmail() on it.
Solution 3; is using friend classes (don't have a lot of experience using them). but since you still have to pass an instance of ContactInformation in order to get m_email. It doesn't seem much different from Solution 2.
Is there any way of making the Teacher class a friend (or something) with the ContactInformation class so I can do something like this:
teacher.getEmail();
Without having to have any getters except from the one in ContactInformation?
The problem with friends classes is that you will lose the posibility (in a future) of using ContactInformation for a different class than Teacher without really gaining much from that.
If PeronalDetails is a member of Teacher and ContactInformation is a member of PeronalDetails. you could simply teacher.personalDetails.contactInformation.m_email which is quite long and requires all these members being public.
A midlle point can be a personalized getter:
public:
Teacher::getEmail(){
return personalDetails.contactInformation.m_email;
}

Is it ideal to put data inside a private class? (C++)

For example, I have this class:
struct bankingFunctionality
{
private:
class bankingData
{
public:
int phoneNum, citizenNum, age, ID;
string name, address;
bankingData* next = nullptr;
};
public:
void input(bankingData*);
void firstUser();
void update(bankingData*);
};
Is it ideal to put the data class in private to "protect" data? Since the only way, I can think of how to access it for input and output is to have functions like void input(...) in public. However, every time I want to call input I would need to create a new object and waste memory.
If you're using this as a way to pass in arguments it's really wasteful and you should consider the traditional getX() and setX() approach for accessors and mutators. You can make these easy to use in a chain style if you return *this at the end of each.
As in:
class bankingData {
int phoneNum, citizenNum, age, ID;
string name, address;
bankingData* next = nullptr;
int getPhoneNum() const { return phoneNum; };
bankingData& setPhoneNum(int n) { phoneNum = n; return *this; };
const std::string& getName() const { return name; };
bankingData& setName(const std::string& n) { name = n; return *this; };
};
Where you can then do:
bankingData bd;
bd.setPhoneNum(111).setName(...);

Is it possible to access a Public Class Member from outside of the main() where it is created?

I am a newbie in c++ and today I was trying to make access a public class member outside of main(), more exactly in another function.
I tried to create pointer to that class, but I fail at accessing its members. I am going to show an example with a few lines of code, Any help would be appreciated.
Class City
{
private:
string name;
public:
string getName()
{
return name;
}
};
bool isCity(string input)
{
if(input== ???) { return true; }
return false;
}
*The problem: how to access public member getName() from the class I create in main() at the question marks
int main()
{
string input;
City test;
cin >> input;
isCity(input);
cin.get();
}
The pointer to Class is not working, the reference pass isn't working either.
Easiest way is to have isCity part of the class and call it as a method of the object test.isCity(input);
The class should be as follow:
Class City
{
private:
std::string name;
public:
std::string getName() const
{
return name;
}
bool isCity(const std::string& input) const
{
return input.compare(name) == 0
}
};
Else you could have a free function (outside of the class), but the signature should provide the class city object as follow:
bool isCity(const City& c, const std::string& input)
{
return input.compare(c.GetName()) == 0;
}
Which then means you have to call the function as follow:
isCity(test, input);

Initialize a STL vector with object of type CPerson (class) in C++?

I have a class CPerson and I want to initialize a vector of type CPerson with object variables. However the compiler says that type name is not allowed. I would like to ask why is that?
class CPerson {
protected:
string m_strName;
Sex m_Sex;
Titles m_Title;
public:
CPerson() {
m_strName = "Peter Petrov";
m_Sex = male;
m_Title = bachelor;
}
//добавяме параметричен к-р
CPerson(string n,Sex s,Titles t) {
m_strName = n;
m_Sex = s;
m_Title = t;
}
~CPerson() {}
void SetName(string strName) {
m_strName = strName;
}
void SetSex(Sex sex) {
m_Sex = sex;
}
void SetTitle(Titles title) {
m_Title = title;
}
string GetName() const {
return m_strName;
}
};
int main(){
vector <CPerson> perr = { CPerson p1,
CPerson p2("I.Ivanov", male, professor),
CPerson p3("A.Stoyanova", female, assistant),
CPerson p4("A.Dimitrova", female, assistant)}
return 0;
}
There are a lot of problems in your code. Here is a version of the code that compiles successfully:
// Example program
#include <iostream>
#include <string>
#include <vector>
enum class Sex {
male, female
};
enum class Titles {
bachelor,
assistant,
professor
};
class CPerson {
protected:
std::string m_strName;
Sex m_Sex;
Titles m_Title;
public:
CPerson() {
m_strName = "Peter Petrov";
m_Sex = Sex::male;
m_Title = Titles::bachelor;
}
//добавяме параметричен к-р
CPerson(std::string n,Sex s,Titles t) {
m_strName = n;
m_Sex = s;
m_Title = t;
}
void SetName(std::string strName) {
m_strName = strName;
}
void SetSex(Sex sex) {
m_Sex = sex;
}
void SetTitle(Titles title) {
m_Title = title;
}
std::string GetName() const {
return m_strName;
}
};
int main(){
std::vector <CPerson> perr({
CPerson(),
CPerson("I.Ivanov", Sex::male, Titles::professor),
CPerson("A.Stoyanova", Sex::female, Titles::assistant),
CPerson("A.Dimitrova", Sex::female, Titles::assistant)
});
return 0;
}
Besides the missing types for Sex and Titles, the main problem was in the syntax of your vector initializer. I assume that you were trying to use an initializer list, but your syntax was all wrong. It looks like you were just copying variable declaration / initialization statements into it, but you need to create new instances of your CPerson class. These instances will then be copied into the vector.
CPerson p2("I.Ivanov", male, professor)
Declares and initializes a variable named p2 of class CPerson on the stack, but this syntax is not valid inside an initializer list, since you're not permitted to declare variables there. Instead use
CPerson("I.Ivanov", Sex::male, Titles::professor)
This creates an instance of CPerson, and this instance is then copied into the vector.