I am doing the Big c++ 2nd edition questions and I am on classes, I am stuck on a question. Basically I have to classes one called "person" and one called "Pemployee", I need to write the member functions of "Pemployee".
They gave me the declarations I need to implement the definitions.
What I don't get how to do is write call name, since it needs to call the private variable "person_data" which is a person object, I cannot access the string name directly but the member function of "person" has a "get_name" function which returns void, I dont understand how to get a string returned if I cannot return from the other definition.
Here are the two classes.
class Person
{
public:
Person();
Person(string pname, int page);
void get_name() const;
void get_age() const; //returns void
private:
string name;
int age; // 0 if unknown
};
class PEmployee
{
public:
PEmployee();
PEmployee(string employee_name, double initial_salary);
void set_salary(double new_salary);
double get_salary() const;
string get_name() const; //assuming I need to call person get_name
private:
Person person_data;
double salary;
};
So once again, how do I call the "Pemployee" get_name to return the string name of the person_data private variable
Typo in the book, Person::get_name should return string
A lot of programming books teach you to add get and set methods to your classes when the variable needs to be read or modified from outside of the class.
You need to create get methods for each of the private variables that your want value access to outside of the class.
You will need a set methods if you want to change the values from outside the class.
Example get method for your class
std::string get_name() const {return this->name;}
These signatures in the class called Person are pointless:
void get_name() const;
void get_age() const;
It is very probable that it is a typo. If it returned string then it whouldn't be pointless.
However if you would not like to change the functions signature or add a new memeber to the Person, then you should declare PEmployee as friend of Person, so member functions of PEmployee can reach private and protected members of Person. You can see below how to do this.
#include <string>
class PEmployee;
class Person
{
public:
friend PEmployee;
Person(){ }
Person(std::string pname, int page);
void get_name() const;
void get_age() const; //returns void
private:
std::string name;
int age; // 0 if unknown
};
class PEmployee
{
public:
PEmployee();
PEmployee(std::string employee_name, double initial_salary);
void set_salary(double new_salary);
double get_salary() const;
std::string get_name() const; //assuming I need to call person get_name
private:
Person person_data;
double salary;
};
Related
In C++, I was just wondering, if I have a base class and a derived class, and I use the set method of the derived class for a value, and then use the set method of the base class on the get method of derived, like so..
student is the base, domestic and international are derived. I have a node and sorted list class which are friends of student. The list and node class works fine, my issue is surrounding object slicing i would assume.
class student
{
template<class T> // these classes not shown because they work
friend class SortedList;
template<class T>
friend class Node;
public:
student();
student(int new_Id,string new_FirstName,string new_LastName,float new_Cgpa,int new_ResearchScore);
string getFirstName() const;
void setFirstName(string new_FirstName);
string getLastName() const;
void setLastName(string new_LastName);
float getcgpa() const;
void setCgpa(string new_Cgpa);
int getresearchscore() const;
void setresearchscore(int new_ResearchScore);
string getT() const; //could be virtual
void setT(string t); // attempt to set derived data member province from domestic student
//object
private:
string FirstName;
string LastName;
float cgpa;
int researchscore;
string T;
}
class domesticstudent : public student
{
public:
domesticstudent(); // constructor
domesticstudent(int the_ID, string The_FN, string The_LN,float The_cgpa, int the_RS,string newProvince);
string getT() const;
void setT(string newProvince);
private:
string province;
};
class internationalStudent : public student
{
internationalStudent();
internationalStudent(int the_ID, string The_FN, string The_LN, float The_cgpa, int the_RS,string newCountry, int new_ToeflScore);
string setT(new_Country);
string getT() const;
private:
string country;
};
// sorted list class member function
// which has a node class to initialize
//all of this works fine
sortedlist::listset(const T& obj)
{ obj.getfirstName();
obj.getLastName();
obj.getT(); // same function for three class methods for reusability
obj.getCgpa();
obj.getresearchscore();
sortedlist(obj); // sortedlist member function that initializes sorted
// single linked list;
}
int main()
{
student base_obj;
domesticstudent derived_obj1;
internationalStudent derived_obj2;
Node<student> node_obj; // tempalte node
SortedList<student> List_obj; // template singly link list
// this is read in through a while loop and .txt file
string firstname, lastname , province; //province is derived variable
int researchscore;
float cgpa; // all other variables belong to base
base_obj.setFirstName(firstName);
base_obj.setLastName(lastName);
derived_obj.setT(province);
base_obj.setT(derived_obj.getT());
base_obj.setcgpa(cgpa);
derived_obj.setresearchscore(researchScore);
list_obj.listset(base_obj);
Node<student> node_obj1; // template node
SortedList<student> List_obj1; //template singly linked list
// read in through another while loop and txt file
base_obj.setFirstName(firstName);
base_obj.setLastName(lastName);
derived_obj2.setT(province);
base_obj.setT(derived_obj2.getT());
base_obj.setcgpa(cgpa);
derived_obj.setresearchscore(researchScore);
list_obj1.listset(base_obj);
}
Ive created two template single linked lists.. i have to merge them into one. this seems to work the way i have that but ive been told thats not OOP. Is there any recommendations on how i could accomplish this, i know they have to be upcasted or initialized as base class so they can be merged later.
I am trying to get the total balance of a list of accounts that are stored in a QList using the QT framework.
My issue is that the total balance needs to access the protected member balance from the class which it does not allow me to do.
This question is from an assignment for university and the question already gave me the UML of the program and there is no getter function for the member variable balance.
My question is, is there any way to access balance from the QList without using a getter function
I have tried adding a new class pointer type, i've tried accessing it directly and tried creating a new class and assigning the class in question passed to it using a assignment constructor
class AccountList: public QList<Account*>
{
public:
~AccountList();
bool addAccount(Account* a);
double totalBalance();
void doInterestCalculations();
QString toString() const;
QStringList customersWithHighestPoints() const;
private:
Account* findAccount() const;
};
class Account
{
public:
Account(QString cn, QString an, double ir, QString ty);
Account(const Account & x);
Account& operator=(const Account& x);
QString getCustName() const;
QString getAccNum() const;
QList<Transaction> getTransaction() const;
QString toString() const;
QString getType() const;
double getInterestRate() const;
virtual void transaction(double amt0) = 0;
virtual void calcInterest() = 0;
protected:
double balance;
QList<Transaction> transactions;
private:
QString custName;
QString accNum;
double interestRate;
QString type;
};
double AccountList::totalBalance()
{
double totalOfBalances = 0;
for(int i = 0; i < this->size(); i++)
{
totalOfBalances+= at(i)->balance;
}
return totalOfBalances;
}
My error using QT Creators IDE is "double Account::balance' is protected" within the context of "totalOfBalances+= at(i)->balance;"
I don't really understand why you can't add a getter for this protected data member.
But if you really don't want to add it, you can do as #Botje suggested. Declare AccountList as friend of Account. This way, AccountList will be able to access the private and protected members of Account.
If you don't know how to do it, add friend class AccountList; in the declaration of Account (Assuming AccountList is already known, if not, do forward declare it).
I have a class named Book that contains an object from class Author. Book's constructor is a private field so I can not use the this class to define objects, so I have another class called BookBuilder which friend to Book and Author helps me to do this.
If I remove the static function problem disappears.
The problem is:
error: no matching function for call to 'Author :: Author ()
In fact I do not have the Author default constructor
class Book {
public:
friend class BookBuilder;
// ... other functions
private:
Book(const std::string title, const std::string publisher,const Author& author, const std::string genre, int isbn, double price):title_(title),publisher_(publisher),author_(author),isbn_(isbn),price_(price),genre_(genre){}
std::string title_;
std::string publisher_;
Author author_;
double price_;
int isbn_;
std::string genre_;
};
class BookBuilder {
public:
static BookBuilder start(){return BookBuilder();}
// ... other functions
private:
std::string title_;
std::string publisher_;
Author author_;
double price_;
int isbn_;
std::string genre_;
};
Your BookBuilder::start method is
static BookBuilder start(){ return BookBuilder(); }
This will try to return a default-constructed BookBuilder. This class has a member
Author author_;
So when you try to construct a BookBuilder, it will try to default initialize the members, including default initializing your auther_ in this case. Therefore Author needs a default constructor for this to work.
I am currently trying to learn C++ and following an instruction. I've researched on mutators and accessors but I need a simple explanation.
class Customer
{
public:
Customer();
~Customer();
private:
string m_name;
int m_age;
};
Right the code above is in a header file. Within the instructions it is asking me to set a public accessors and mutator for both data. How do I do this?
Also it mentions checking the age is not negative in the mutator. I know how to implement the code but I'm just confused on where to place it. Do I place the validation in this header file? or in the .cpp? or in the main method?
I know this sounds all silly and I'm sure simple but I'd like to try and understand this.
Please note that this is basic C++.
Accessor - Member function used to retrieve the data of protected members.
Mutators - Member function used to edit the data of protected members.
In your case,
class Customer
{
public:
Customer();
~Customer();
string getName(); // Accessor for the m_name variable
void editName(string in); // Mutator for the m_name variable
private:
string m_name;
int m_age;
};
Inside your .cpp file:
string Customer::getName() {
return m_name;
}
void Customer::editName(string in) {
m_name = in;
}
I have a data structure "Person"
struct Person
{
protected:
string name;
int age;
string address;
...
}
I want to create "views" around this structure to separate out access to different member variables:
class PersonRead: public Person
{
public:
string getName() {..}
int getAge() {...}
...
}
class PersonUpdate: public Person
{
public:
void setAddress( string address_ ) {...}
void setAge( int age_ ) {...}
...
}
I use this to only expose those methods/variables which are really required:
int main()
{
...
writePersonDataToFile ( (PersonRead) personObj );
updatePersonData ( (PersonUpdate) personObj);
...
}
Though the above code serves my purpose, there are several issues including:
The public inheritence here is not exactly an 'is-a' relationship
I need to derive IndianPerson from Person, and all the corresponding interfaces. This leads to bad diamond pattern:
struct IndianPerson: public Person {};
class IndianPersonRead: public IndianPerson, public PersonRead {}; //Person Class common, Diamond pattern here!
Is there a name for such a design pattern? What are better ways to implement this pattern? I have a feeling Policy classes might help, but cant figure out how to implement this
Any examples would be great help
For your scenario this might seem like overkill but, if you want fine grained control over which classes can call different methods on your class the c++ client-attorney idiom idiom might be appropriate.
For a detailed description of this idiom see http://drdobbs.com/184402053
Here is a rough example (note: this has not been compiled, although it is based on production code I am currently using):
class Person
{
public:
/// constructor destructor etc:
private:
string getName() { return name; }
public:
/// Writer Attourney that access to allows class PersonReader access
/// to getXXX functions
class ReaderAttorney
{
private:
/// Add additional reader member functions...
static string readName( Person& p )
{
return p.getName();
}
// Make any classes that shuold be allowde read access friends of the
// attorney here
friend class PersonReader;
};
/// Writer Attourney that access to allows class PersonWriter access
/// to setXXX functions
class WriterAttorney
{
private:
/// Add additiona reader member functions...
static string setName( Person& p, const string& newName )
{
p.setName( newName );
}
friend class PersonWriter;
};
private:
string name;
int age;
string address;
};
This can be used as follows:
void PersonWriter::setPersonDetails( const string& name, int age .... )
{
// PersonWriter is a frend of WriterAttorney and is granted access
Person::WriterAttorney::setName( name );
Person::WriterAttorney::setName( age );
// Note this will fail, since PersonWriter is not a friend of
// ReaderAttorney, ergo it is not granted read permission:
Person::ReaderAttorney::readName();
}
I think that your approach is not correct at all: PersonRead and PersonUpdate are not Persons. They read and modify Person data but are not really Person.
In the same way, IndianPersonRead and IndianPersonUpdate are not an IndianPerson.
I separate this relationship in following:
PersonRead use Person
PersonUpdate use Person
IndianPerson inherits from Person: is a Person
IndianPersonRead inherits from PersonRead and use IndianPerson
IndianPersonUpdate inherits from PersonUpdate and use IndianPerson
I show an example of my apporach:
#include <string>
#include <iostream>
using namespace std;
struct Person
{
string getname() const { return name; }
string getaddress() const { return address; }
void setaddress(const string & address_) { address = address_; }
void setname(const string & name_) { name = name_; }
protected:
string name;
int age;
string address;
};
class PersonRead
{
public:
string getname(const Person & p) { return p.getname(); }
};
class PersonUpdate
{
public:
void setAddress(Person & p, const string & address_ ) {p.setaddress(address_); }
void setname(Person & p, const string & name_ ) {p.setname(name_); }
};
struct IndianPerson : public Person
{
string gettribe() const { return tribe; }
void settribe(const string & tribe_) { tribe = tribe_; }
protected:
string tribe;
};
struct IndianPersonRead : public PersonRead
{
public:
string gettribe(const IndianPerson & p) const { return p.gettribe(); }
};
struct IndianPersonUpdate : public PersonUpdate
{
public:
void settribe(IndianPerson & p, const string & t) { p.settribe(t); }
};
int main(int argc, char **argv)
{
IndianPerson ip;
IndianPersonUpdate ipU;
IndianPersonRead ipR;
ipU.settribe(ip, "Cheroki");
ipU.setname(ip, "Charly");
cout << ipR.getname(ip) << " : " << ipR.gettribe(ip) << endl;
}
First of all I will agree with the Tio's point of view PersonUpdate is not a Person so there is a wrong inheritance usage. Also I believe that you need to make your classes with target to represent the real world so classes like PersonUpdate are wrong because they represent the action and not the object.
In your case one solution could be to use the visitor design pattern, so the Person could accept a especially designed IPersonStream interface in order to perform the serialization in classes which will implement this interface.
Person stream will accept the persons attributes on it or for good the Person's memento take a look on memento design pattern, and serialize it to xml or whatever you want.
I don't have a design pattern name, but to resolve your concerns, I would swap the inheritance relation and let Person inherit from the PersonReader and PersonWriter interfaces. This way, objects that must only read from Person use the PersonReader interface and as such promises to not change it.
By making every member of Person private, you can even make sure that Person is not accessed in another way, but then every class that inherits from Person should have these members private.