Inheritance and accessing attributes - c++

I am learning OOP in C++, and I have written this piece of code to learn more about inheritance.
#include<bits/stdc++.h>
using namespace std;
class Employee {
public:
string name;
int age;
int weight;
Employee(string N, int a, int w) {
name = N;
age = a;
weight = w;
}
};
// this means the class developer inherits from employee
class Developer:Employee {
public:
string favproglang; //this is only with respect to developer employee
// now we will have to declare the constructor
Developer(string name, int age, int weight, string fpl)
// this will make sure that there is no need to reassign the name, age and weight and it will be assigned by the parent class
:Employee(name, age, weight) {
favproglang = fpl;
}
void print_name() {
cout << name << " is the name" << endl;
}
};
int main() {
Developer d = Developer("Hirak", 45, 56, "C++");
cout << d.favproglang << endl;
d.print_name();
cout << d.name << endl; //this line gives error
return 0;
}
Here the developer class is inheriting from the employee class, but when I am trying to print the name of the developer from the main function cout << d.name << endl; I am getting this error 'std::string Employee::name' is inaccessible within this context.
I am not getting why I am getting this error? I have declared all the attributes as public in the parent class. This error is not their when I am trying to access the name from the developer class itself as you can see in the function print_help(). Moreover I can also print d.favproglang from the main function, but then why not d.name? Any help will be highly appreciated. Thank you.

This is because the default access control for inheritance is "private".
If you change this:
// this means the class developer inherits from employee
class Developer: Employee {
to this:
// this means the class developer inherits from employee
class Developer: public Employee {}
By default, class inheritance is "private" inheritance and struct inheritance is "public" inheritance. Private inheritance means public and protected members of the base class will be treated like private members by the child class.
You can override this default behaviour by explicitly writing public, private or protected in front of the base class name.
Search "c++ base class members access control" to learn more.

There are 2 solutions(straightforward) to this.
Solution 1
Replace the class keywords for both the Employee and Developer class with the keyword struct. Note even if you replace class keyword for Developer with struct and leave the class keyword as it is for Employee then also this will work.
Solution 2
Add the keyword public in the derivation list as shown in the next line:
class Developer:public Employee

Related

compilation error due to private variable declaration inehritance

I get the following error compiling the code below:
Student.cpp:20:9: error: ‘std::string Student::name’ is private within this context
20 | name = _name;
| ^~~~
Student.cpp:7:12: note: declared private here
7 | string name;
#include <iostream>
using namespace std;
class Student
{
private:
string name;
};
class UndergraduateStudent : public Student
{
};
class GraduateStudent : public Student
{
};
class Freshman : public UndergraduateStudent
{
Freshman(string _name)
{
name = _name;
}
};
What could be the reason for this?
I want to keep UndergraduateStudent class as abstract
I had a hard time understanding public, private, and protected when I was learning object-oriented programming in C++, and thought that I would share a few thoughts to hopefully clear some of this up.
First of all, public, private, and protected are used to determine the level of accessibility of a variable or method in a class. If you declare a variable as private, you can access that variable inside of the class that it was declared in, but nowhere else. With protected, you may access that variable in the child classes of the class it was declared in. And with public, you can access that variable anywhere.
So what does this mean?
Using your code, we start off with this:
#include <iostream>
using namespace std;
class Student
{
private:
string name;
};
class UndergraduateStudent : public Student
{
};
class GraduateStudent : public Student
{
};
class Freshman : public UndergraduateStudent
{
Freshman(string _name)
{
name = _name;
}
};
The reason that you got a compile error is that you tried to access the variable "name" in the Freshman class. Freshman is a child class of Student (well, it's actually a child class of Undergraduate Student which is a child of student, but the concept still applies). Because of this, any method in the Freshman class will only be able to access protected and public variables and methods in the Student class. Therefore, if you want to access "name" in the Freshman class, you must change it from private to either protected or public.
However, after doing this, you might wonder how to access private and protected variables from outside of the class? In main() how would you get the value of a freshman's name if it is private or protected? The answer to this is getters and setters. Modifying your code a little bit, you get something like this:
#include <iostream>
using namespace std;
class Student
{
protected:
string name;
public:
string getName(){
return name;
}
void setName(string _name){
name = _name;
}
};
class UndergraduateStudent : public Student
{
};
class GraduateStudent : public Student
{
};
class Freshman : public UndergraduateStudent
{
public:
Freshman(){}
Freshman(string _name)
{
name = _name;
}
};
As you can see, I added a couple of public methods in Student, getName() and setName(). I also added some constructors in the Freshman class. The important part about these Student methods is that they are public, and can be accessed anywhere. It's not difficult code to understand, essentially getName() returns the value of the private variable "name", and setName() is able to change that value.
So lets say that in main() I wanted to create a Freshman object, and declare her name as Sarah, and print out that result.
int main(){
Freshman freshman("Sarah");
cout << freshman.name;
}
If I did this, I would get a compile error, because I am trying to access the protected variable "name". If I wanted to access the value, I would have to access it through the public method getName(). Therefore:
int main(){
Freshman freshman("Sarah");
cout << freshman.getName();
}
This would print out the correct result of "Sarah". Now, let's say that I spelled her name wrong, and it turns out there's no 'h' in her name. Then, I would have to call the public method of setName in order to change her name to something else.
int main(){
Freshman freshman("Sarah");
freshman.setName("Sara");
cout << freshman.getName();
}
This would now output the value of "Sara". These are just some basic examples of how to use private, protected, and public, sorry if it was a little bit lengthy. I hope that it can help you if you don't quite understand exactly how to use them yet. Just practice, it comes after doing it a few times.

C++ : Access of a child member from a parent class

Assuming I have this class below : (I minimized the program as much as I could and deleted the private members and functions that are not related to the issue ).
class CBookings
{
public:
CBookings() = default;
private:
std::vector<CPerson *>Persons;
};
Where CPerson is a parent class :
class CPerson
{
public:
CPerson() = default;
friend class CBookings;
protected:
std::string Name;
};
and CStudent the child of CPerson :
class CStudent : public CPerson
{
public:
CStudent() = default;
private:
unsigned int MatriculationNr;
};
In my program I did a load function where I extracted all the names and their MatricualionNrs from a file and put them into the vector Persons using this method :
if (Line.compare("<student>") == 0)
{
CStudent *S1 = new CStudent();
S1->load(src); //Load function is missing in class but ignore it
Persons.push_back(S1);
}
Now if I want to make a print() function to print the names and their MatricualionNrs.
How can I have access to the child member in this case ? I know that printing the Name of CPerson will require me to add CBookings as a friend class to CPerson but how about the MatriculationNr ?
void CBookings::print()
{
for (int i = 0 ; i < Persons.size() ; i++)
{
cout << Persons[i]->Name << " " << (...MatriculationNr??.) << endl;
}
Not really giving you access to child member, but this is a more OOP approach.
If the only thing you were trying to do is to print the different types of Person classes, then a more proper way of doing it is to define a virtual print function in Person class, then override print function in each child classes, and call person->print() in your Booking class.
In your Person class:
class CPerson
{
public:
virtual void Print()
{
std::cout << Name << "\n";
}
protected:
std::string Name;
}
In your Student class:
class CStudent
{
public:
void Print()
{
CPerson::Print(); // this will execute the Print() you defined in CPerson
std::cout << MatriculationNr << "\n";
// Or you can also just cout all information from here:
// std::cout << Name << ", " << MatriculationNr << "\n";
}
private:
int MatriculationNr;
}
Then in your Booking class, you just call print() from all Person:
void CBookings::Print()
{
for (int i = 0 ; i < Persons.size() ; i++)
{
Persons[i]->Print();
}
}
By doing this, you also don't need to declare Booking as a friend in Person class.
Edit:
In case you were wondering why you want to do it this way:
The fact you used a vector<Person*> implied that there might be other types of Person included in the vector, such as Staff. If not, then you should have just used vector<Student*> instead.
In the case you might also have Staff in it, then doing something like:
std::cout << Persons[i]->MatriculationNr wouldn't make any sense because of course Staff would not have such member in it. Instead, Staff might have a Salary, or whatever in it.
If you keep using the friend class to access private members, you would also need to check each Person's type, if they are a Student or a Staff, then call different cout function based on that.
This becomes tedious if you have many different children types, and your Booking::Print() just becomes a huge if - else if - else if block. And you have to update Booking every time you either change the members of your Person classes, or add another child class to Person.
By having overridden Print() function in your children classes, you don't need to do anything to Booking::Print(), they would all use the same person->Print() from your Booking class.
You cannot access the members of CStudent unless you have a CStudent* pointer.
If your base class CPerson has at least one virtual method, you can use dynamic_cast to safely get a pointer to the actual child class. If the pointer does not point to the proper child class you'll receive a nullptr.
CStudent* pStudent = dynamic_cast<CStudent*>(Persons[i]);
if (pStudent)
{
cout << pStudent->Name << " " << pStudent->MatriculationNr << endl;
}
Doing things this way can be a bad code smell, because it bypasses the principle that a class should be responsible for its own actions. It can also get cumbersome as the number of child classes grows or the number of exceptional member accesses increases - that can lead to bugs.

C++ Multiple inheritance problem on accessing second derived class variables

I have a base class A and in this class, there is a vector of the derived class B, and I add class C objects to this list (C is a derived class of B).
But now I am not able to access any variable either from B or C.
My class structure goes like this:
Skill.h
class Skill
{
public:
Skill()
{
}
vector <AttackSkill*> attacks;
vector <UtilitySkill*> utilities;
vector <MoveSkill*> movement;
};
AttackSkill.h
#pragma once
#include "Skill.h"
class AttackSkill :
public Skill
{
public:
AttackSkill()
{
}
string skillName;
int dmgMod;
int baseAcc;
};
One of the skills
#pragma once
#include "AttackSkill.h"
class Axeblade :
public AttackSkill
{
public:
Axeblade()
{
skillName = "Axeblade";
dmgMod = 0;
baseAcc = 72;
}
};
This is how to add new skill
attacks.push_back(new Axeblade);
I just want to be able to access variables.
Example:
"skillPtr" is a pointer to Skill object
for (int i = 0; i < skillPtr->attacks.size(); i++) //No problem here
{
cout << "Skill " << i << ") " << skillPtr->attacks[i]->skillName << endl;
}
Error C2039 'skillName': is not a member of 'Skill'
I am doing some guesswork here since the question is not fully specific but it might help…
Your class Skill contains three vectors (aggregation) and it’s inherited by subclasses defining skill types (inheritance). You should break these two principles apart. There should be one class containing the vectors for a character, let me call it SkillSet. (By the way, you should never issue using namespace in a header file.)
class SkillSet
{
public:
std::vector <AttackSkill *> attacks;
std::vector <UtilitySkill *> utilities;
std::vector <MoveSkill *> movement;
};
Then there will be another base class for all skills which would contain the properties which all skills have:
class Skill
{
public:
std::string skillName;
};
Then you can inherit this new Skill class:
class AttackSkill :
public Skill
{
public:
int dmgMod;
int baseAcc;
};
class Axeblade :
public AttackSkill
{
public:
Axeblade()
{
skillName = "Axeblade";
dmgMod = 0;
baseAcc = 72;
}
};
After creating and filling a SkillSet object:
SkillSet hero0;
hero0.attacks.push_back(new Axeblade);
You can simply access its public members:
std::cout << hero0.attacks[0]->skillName;
See the example of my code.
A few more notes to consider:
You don’t need vectors of pointers, you can put the objects directly to the vector. A vector is not a plain array.
Instead of making the properties public, consider using setters and getters.
Your code contains empty constructors. There is no need to write a constructor that is empty.
On the other hand, if your code contains objects created using new, you should delete them, e.g. in a destructor.

How to use a member function from a parent class with the same name (via this->)?

Heres the gist of my program:
I have a base class called Person. It has a child called President. I am trying to create a "printInfo" function in the President class that prints all of its attributes from both classes.
The simplest change was to simply differentiate the functions by changing the names, but I was wondering if there was a way to do this without changing them.
(The code below just includes the relevant parts, I left out a bunch of other member functions to make it easier to read)
class Person : public Address {
public:
void printInfo(); // this prints the name and birthday
private:
string fname, lname, sex;
int month, day, year;
};
class President : public Person {
private:
int term;
public:
void printInfo(); // this prints term
};
void President::printInfo() {
cout << term << " : ";
this->printInfo(); //need this to use the person version of itself
};
What I want:
1 : George Washington ....
Actual Result:
1 : 1 : 1 : ....
You can call the member function of base class by adding Person:: prefix. e.g.
void President::printInfo() {
cout << term << " : ";
Person::printInfo();
};
BTW: It's better to make printInfo and the destructor of Person virtual.

Inheritence in c++

#include<iostream.h>
#include<conio.h>
#include<stdio.h>
class person {
private: char name[50];
int age;
public: void get_name() {
cout<<"Enter name"<<endl;
gets(name);
}
void put_name() {
cout<<"Name : ";
puts(name);
cout<<endl;
}
void get_age() {
cout<<"Enter age"<<endl;
cin>>age;
}
void put_age() {
cout<<"Age : "<<age<<endl;
}
};
class student : public person {
private : int roll;
public : void get_roll() {
cout<<"Enter roll"<<endl;
cin>>roll;
}
void put_roll() {
cout<<"Roll : "<<roll<<endl;
}
};
int main() {
student A;
A.get_name();
A.get_roll();
A.get_age();
A.put_name();
A.put_age();
A.put_roll();
getch();
clrscr();
return 0;
}
There are following queries:
If private members of class person are not inherited in class student then how can an instance of class student store values in them?
Shouldn't the variables just not exist in the class student?
Note: I am using old compiler for a college project.
If a Student wants to access the Person fields, the simplest way is make them protected, so they can be accessed by all derived class of Person.
Another way is use public getter/setter methods (you can even set them protected, but at this point is better use protected fields), in this way all classes can see and set the fields of Person.
Indeed, even if a variable is declared private in the base class, it exist in the derived class ( a Student is in any case a Person, so the field in Person must be initialized) but it can't be reached by her.
A is an object of type Student and it can access protected or public member function and data member of class Person. Now answer to your query, you are trying to use the function of class Person using object of class Student which is possible (as inherited publicly) and since the function and those private data member are part of same class (Person), so those function can use the variable.
Note : private, public and protected member have no effect within same class.