how to call a child class inside its parent class? - c++

class Society
{
void add_student(string name,string home_town)//add student to society
{
Student a;
a.set_name(name);
a.set_home_town(home_town);
}
bool same_community(Student s1, Student s2){}//check if student 1 & student 2 are in the same community
void join_communities(Student s1,Student s2){}//join communities which student 1 & student 2 are in
int num_of_communities(){}//return the total number of communities inside the society
float max_diversity(){}//return the highest diversity between all communities
};
class Community : public Society
{
void add(Student new_student){}//add new student to community
bool contains(string name_student){}//whether community contains a student named name_student
void join(Community other_community){}//add all students in other_community to this community
float diversity(){}//return the number of distinct hometowns/names for this community
};
class Student :public Community
{
string name, string home_town;
public:
void set_name(string a){name=a;}
void set_home_town(string b){home_town=b;}
string get_name() const{return name;}
string get_home_town() const{return home_town;}
};
I have a parent class named Society and I would like to use its child class named Student in some of the functions.how can I do this?

I agree with other comments, but if necessary, you can apply CRTP pattern with this form. However, this solution only apply to Student communities, you can't mix different community members:
template<typename T>
class Society
{
void add_student(string name,string home_town)
{
T student;
student.set_name(name);
......
}
....
};
template <typename T>
class Comunity : public Society<T>
{
void add(T new_student){}//add new student to community
....
};
class Student : public Comunity<Student>
{
.....
}

Related

How do I create a sub class in C++

I am new to C++. I am trying to create a subclass of a base class, but it does not seem to work.
I have the base class Person and a sub class Student, and the Person class is complete. Now I want to create a sub class Student. I have the following code:
namespace Uni
{
class Student : public Person
{
private:
int enrollNumber_;
string majorCourse_;
int averageGrade_;
Student(const Student &);
public:
Student(int enrolled_number, string major_course, int average_grade);
~Student();
const int getenrollNumber() const { return enrollNumber_; }
const int getAverageGrade() const { return averageGrade_; }
const string getMajorCourse() const { return majorCourse_;
};
}
The problem is that the IDE says that on the line class Student : Person that Person [is] not a class or struct name.
How can I create the subclass Student?

C++ prevent inherit specific public member of base class

How can I prevent a public member to be inherited by it's derived class? Like, if I have this:
class Person {
public:
enum { MALE, FEMALE, BOTH };
Person(std::string name, int gender)
: _name(name)
{
switch (gender) { /* processing here */ }
}
protected:
std::string _name;
};
class Male : public Person {
public:
Male(std::string name)
: _name(name, 0) { }
};
The reason I want to do this is, I want to be able to instantiate a person class with something like:
Person person("The Name", Person::MALE);
But, because the enum is public this is also available:
Male::MALE
Male::FEMALE
Male::BOTH
which doesn't make any sense anymore. How can I prevent the derived class to be able to access those enum values, but make it available for public from the base class?
If you insist on keeping the enum within the base class, you can place the enum in a protected section.
class Person {
protected:
enum Gender { MALE, FEMALE, BOTH };
Person(std::string name, Gender gender)
: _name(name)
{
switch (gender) { /* processing here */ }
}
std::string _name;
public:
virtual ~Person () {}
//...
};
A class that derives from Person publicly will still have access to the enum values, but users of the derived class will not.
class Male : public Person {
public:
Male (std::string name) : Person(name, MALE) {}
//...
};
Thus, a Male can use MALE, but users of Male will not see Male::MALE, Male::FEMALE, nor Male::BOTH, which was one of your original issues. As to your questions, you don't really want to deny the derived class access, since you want the derived class to be able to specify the Gender. And you should not really allow any direct users of Person. Instead, a user of Person picks one of the correct derived classes, which will then establish Gender properly.
class Female : public Person {
public:
Female (std::string name) : Person(name, FEMALE) {}
//...
};
class Transgender : public Person {
public:
Transgender (std::string name) : Person(name, BOTH) {}
//...
};
std::shared_ptr<Person> p = std::make_shared<Female>("Beth");
The comments in the OP suggest a rethinking of your design, and probably that is the best alternative.
Still, if you want to keep up with what you wrote in the answer, one possibility is to derive protectedly from your base class
class Person {
public:
enum { MALE, FEMALE, BOTH };
Person(std::string name, int gender)
: _name(name)
{
switch (gender) { /* processing here */ }
}
protected:
std::string _name;
};
class Male : protected Person
{ //^^^^^^^^^
public:
Male(std::string name)
: Person(name, 0) { }
void foo() { FEMALE; } // still ok, a public field derived protected'ly is accessible
};
int main()
{
Male male("Joe");
male.MALE; //error, cannot call the enum from outside the class
}
the problem seems to be a literate one, there is no problem with the code per se, but in viewing the code as a language reflecting common notions.
In this sense i would suggest the following answer:
have a factory (or factory method) where the enum is public only in that factory. In other words create a new factory Human and have all base and derived classes using Human enums. Then the base class can still be Person but Person does not have any enum MALE/FEMALE/etc.. only the Human factory does, and it is not a base class that is subclassed. This would result in code which can be read literaly like this:
Person person("The Name", Human::MALE);
You can also use Gender factory (instead of Human) like this (to be even more literate and separate the inter-dependencies):
Person person("The Name", Gender::MALE);
Note that a base class includes the lowest common denominator that all derived classes must share. So since the derived classes Male Female etc are not supposed to share the gender enum then it should not be part of the base class, but a class or construct in itself which is then used by Person classes and its derivatives.
Simple make the Person class abstract using a protected constructor:
class Person {
public:
enum Gender {
MALE,
FEMALE,
BOTH
};
protected:
// Protected constructor can only be called from subclasses.
Person(std::string name, Gender gender)
: _name(name)
{
switch (gender) { /* processing here */ }
}
protected:
std::string _name;
};
class Male : public Person {
public:
Male(std::string name)
: Person(name, MALE)
{
}
};
If the gender is anyway independent from the Person class, just move it out of the class:
enum Gender {
GenderMale,
GenderFemale,
GenderBoth
};
class Person //...
class Male // ...
You can also encapsulate the Gender into a own class:
class Gender {
public:
enum Type { Male, Female, Both };
Gender(Type type);
Gender(const Gender &copy);
Gender& operator=(Gender &assign);
public:
bool operator==(const Gender &other) const;
// etc.
public:
std::string toString() const;
};

Communication on Base class's collection's generic type

Please help me solve the following C++ design Questions
Class Office
{
std::list<Employees *> m_Employees;
string m_Address;
void AddEmployee(Employees *employee);
string GetAddress();
}
Class SalesOffice : public Office
{
int m_TotalEmployees_SalesPerYear;
int GetSalesPerYear();
}
Class FinanceOffice : public Office
{
int m_TotalEmployees_ProfitPerYear;
int GetProfitPerYear();
}
Class BookKeepingOffice : public Office
{
int m_TotalEmployees_RecordsPerYear;
int GetRecordsPerYear();
}
Class Employees
{
int id;
int GetID();
}
Class SalesEmployees : public Employees
{
int m_SalesPerYear;
int GetEmployeeSalesPerYear();
}
Class FinanceEmployees : public Employees
{
int m_ProfitPerYear;
int GetEmployeeProfitPerYear();
}
Class BookKeepingEmployees : public Employees
{
int m_RecordsPerYear;
int GetEmployeeRecordsPerYear();
}
Class Office has a list of Class Employees. This composite relation cannot be changed.
Apparently, Any type of Office only knows Employees.
Question: How does SalesOffice's GetSalesPerYear can access GetEmployeeSalesPerYear()
Note: I do not want to typecast employees in each office.
Any suggesstion on design and design patterns?
int GetEmployeeSalesPerYear(); should be defined as virtual method of Employee, returning 0 and SalesEmployees should reimplement it.

C++ multiple inheritance

Please don't question the really odd hierarchy of workers in this code here, I have no idea why anyone would want something like this, but I decided to give myself an exercise in Multiple Inheritance, just to be sure I fully understood it. So here's the result.
using namespace std;
class Employee
{
protected:
string name;
public:
string getname()
{
return name;
}
void setname(string name2)
{
name = name2;
}
Employee(string name2)
{
name = name2;
}
Employee(){}
};
class Manager : public Employee
{
public:
string getname()
{
return ("Manager" + name);
}
Manager(string name2) : Employee(name2){}
Manager() : Employee(){}
};
class Supervisor : public Manager,public Employee
{
public:
Supervisor(string name2) : Manager(name2) , Employee(name2){}
Supervisor() : Manager() , Employee(){}
string getname()
{
return ("Supervisor" + Employee::getname());
}
};
Hopefully you're understanding what I'm trying to do here. I'm getting something about an "ambiguous conversion between derived class 'Supervisor' and base class 'Employee.'" So what do I do?
Actually, the way you have defined Supervisor class, its object will have two subjects of type Employee, each coming from it base classes. That is causing problem.
The solution is to use virtual inheritance (assuming you need multiple inheritance) as:
class Manager : public virtual Employee
Hope you note the virtual keyword here. :-)
Everybody has already covered virtual inheritance, but I'd suggest reading the C++ FAQ as well.
http://www.parashift.com/c++-faq-lite/multiple-inheritance.html
You need a virtual inheritance in this case:
#include <iostream>
#include <string>
using namespace std;
class Employee
{
protected:
string name;
public:
string getname()
{
return name;
}
void setname(string name2)
{
name = name2;
}
Employee(string name2)
{
name = name2;
}
Employee(){}
};
class Manager : public virtual Employee
{
public:
string getname()
{
return ("Manager" + name);
}
Manager(string name2) : Employee(name2){}
Manager() : Employee(){}
};
class Supervisor : public Manager,public virtual Employee
{
public:
Supervisor(string name2) : Manager(name2) , Employee(name2){}
Supervisor() : Manager() , Employee(){}
string getname()
{
return ("Supervisor" + Employee::getname());
}
};
This problem is also known as Diamond inheritance problem:
http://en.wikipedia.org/wiki/Diamond_problem
Supervisor contains two objects of type Employee, the direct one and the one over Manager. It is ambiguous to call Employee methods on a Supervisor in consequence (which Employee should be called?). You might want to employ virtual multiple inheritance instead.

Multiple class inheritance?

Based on the figure below, I wrote my code.
This is the code I wrote:
#include<iostream>
#include<string>
using namespace std;
class person
{
private:
int code;
string name;
public:
void setCode(int c) { code=c; }
int getCode() { return code; }
void setName(string s) { name=s; }
string getName() { return name; }
};
class account : public person
{
private:
double pay;
public:
void setPay(double p) { pay=p; }
double getPay() { return pay; }
};
class admin : public person
{
private:
string experience;
public:
void setExper(string e) { experience=e; }
string getExper() { return experience; }
};
class master : public account, public admin
{
};
int main()
{
master mastObj;// create master object.
mastObj.setName("John");
system("pause");//to pause console screen, remove it if u r in linux
return 0;
}
The compiler showed these errors:
Error 1 error C2385: ambiguous access of 'setName'
Error 2 error C3861: 'setName': identifier not found
Error 3 IntelliSense: "master::setName" is ambiguous
It is classic example of Diamond Problem in C++ when you use multiple inheritance.
The solution is : Virtual inheritance
That is, you should do this:
class account : public virtual person
{ //^^^^^^^note this
//code
};
class admin : public virtual person
{ //^^^^^^^note this
//code
};
I just found really good posts on this site, so I would redirect you to those answers here:
Virtual inheritance in C++
Virtual Inheritance Confusion
Virtual inheritance in C++
In C++, what is a virtual base class?
which also means, this topic should be voted for close.
You need virtual inheritance:
class account: public virtual person{
....
}
class admin: public virtual person{
...
}
PS And your pay, code fields lack initialization! This could lead to embarassing errors (like paying the cleaner several million of dollars :)):
#include<iostream>
#include<string>
using namespace std;
class person
{
// ...
person() : code(0), name("anonymous") {}
};
class account : public virtual person
{
// ...
account() : pay(0) {}
};
class admin : public virtual person
{
// ...
admin() : experience("unknown") {}
};
you may use mastObj.master::admin::person::setName("John");