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;
}
Related
Consider this example:
class Child
{
private:
string m_Name;
public:
string* GetNameAccess()
{
return &m_Name;
}
};
class Parent
{
private:
Child m_Child;
public:
void DoSomething()
{
string *pChildName = m_Child.GetNameAccess(); // Is this the right thing to do?
*pChildName = "NewName";
}
};
In has-relation we know that Parent object owns the child object (i.e controls the lifetime of child).
So is Parent allowed to directly access the private members of child and alter them ?
Although having a public function that returns a pointer to a private data member is legal in C++, it breaks the whole point of encapsulation. As mentioned in the comments, if you want to provide such 'direct' access to the data member, then just make it public.
But there are many good reasons why a data member should be private – such as offering some control(s) over what values are allowed or disallowed for that member. In such circumstances, you should provide genuine 'getter' and 'setter' functions to allow controlled access to that private member from outside the class. The 'getter' should not allow modification of the data (so returning a const& reference is generally appropriate) and the 'setter' should perform the required checks on the value it is given, before making a modification to the data.
Here is a very brief outline of how such a 'getter' and 'setter' may look for your example:
#include <string>
class Child {
private:
std::string m_Name;
public:
const std::string& GetName() { // The "const" prevents modification with the getter
return m_Name;
}
void SetName(const std::string& name) {
// A real setter allows error checking ...
if (name != "Attila the Hun") m_Name = name;
}
};
class Parent {
private:
Child m_Child;
public:
void DoSomething() {
std::string temp = m_Child.GetName();
if (temp.empty()) temp = "New Name";
else temp += " (Modified)";
m_Child.SetName(temp);
}
};
This short snippet demonstrates how you could prevent a parent naming their child, "Attila the Hun," which is perhaps a reasonable precaution for a setter function to implement.
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;
};
I am new into classes, and I have been trying to create this simple class code but every time I get an error. It works fine when I don't use the access specifier private, but I want to practice how to use private. Could you please tell me what's wrong?
#include <iostream>
#include <string>
using namespace std;
class Student
{
private:
string name;
int ID;
public:
void setName(string);
string getName();
void setID(int);
int getID();
};
void Student::setName(string n)
{
name=n;
}
string Student::getName()
{
cout<<name;
return name;
}
void Student::setID(int i)
{
ID=i;
}
int Student::getID()
{
cout<<ID;
return ID;
}
int main ()
{
Student S;
cout<<"Enter Student name: ";
cin>>S.name;
cout<<"Enter students ID: ";
cin>>S.ID;
cout<<"The student's name is "<< S.name<<endl;
cout<<"The student's ID is "<< S.ID<<endl;
return 0;
}
In your main function you are trying to access the name and IDmember of your class. Which are private... Since you are outside the scope of the class Student, the compiler shouts at you.
You should do this (as you've implemented setters and getters):
int ID(0);
std::string name;
std::cin >> name;
S.setName(name);
std::cin >> ID;
S.setID(ID);
You have to access your private fields using setters/getters to set or retrieve their values, you can't use them with the class dot notation because they're private and you can access to them only using public methods
What's wrong : You are accessing private members without using a class member function (outside of the class scope).
Private members are useful when you want to protect a value from uncontrolled access. Like when the modification of a value must undergo a certain verification (which would be implemented in class functions).
In your code, you made sure name and ID are private, which means both can only be accessed using class functions (like the constructor or the getter and setter).
If you wanted, you could create a class named classroom (which would contain many students, stored in a vector).
In that class, you could make sure than when a student is added, it's ID is automatically generated and does not equal any other ID. In that case, it would be important to put the student vector private since it would require some sort of validation.
class Student
{
private: // anything that wants to access members below
// this must be defined as a class member, or the equivalent
string name;
int ID;
public:
void setName(string); // can access private members
string getName(); // can access private members.... should be const
void setID(int); // can access private members
int getID(); // can access private members, should be const
};
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.
I know this subject has been covered and re-talked, but I still get stuck every time I need to do something like that, and the internet is full of different answers.
so I decided to simply ask how to deal with such situation once and for all.
Lets say I have the following class:
class PETS_EXPORT_API dog
{
public:
dog(std::string name):_name(name){}
~dog(){}
private:
std::string _name;
};
Obviously this code would generate a warning because I'm trying to export std::string. How do I solve such issue ?
thanks!
Alternative to Joe McGrath's answer:
If you really want your clients to have access to Dog public & protected interface, and does not make sense to have an abstract interface,
You could use the pImpl idiom, to hide the private interface.
Additionally you could export the string in the form of chars
Hide your original dog:
class Dog_Impl // your original class
{
public:
Dog_Impl(std::string name):_name(name){}
~Dog_Impl(){}
string::get_name();
private:
std::string _name;
};
Put this into your API:
class Dog_Impl; // fwd declaration
class PETS_EXPORT_API Dog {
public:
Dog(const char *name);
~Dog();
const char *get_name();
private:
Dog_Impl *pImpl;
};
The implementation should simply pass all public & protected interface to the pImpl:
Dog::Dog(const char *name)
{
pImpl = new Dog_Impl(name);
}
Dog::~Dog()
{
delete pImpl;
}
const char *Dog::get_name()
{
return pImpl->get_name().c_str();
}
You don't want to export the private members. Only the public interface. Make an abstract base class and export it.
struct DogInterface
{
virtual string IAmADog(void) = 0; // your public interface goes here
};
// Factory function that creates dogs
extern "C" PETS_EXPORT_API DogInterface* APIENTRY GetDog();
If you just want to export the string for access
__declspec(dllexport) const char* MyExportedString()
{
return myString.c_str()
}