Multiple Inheritance need to acces to private variable - c++

I don't know how access to private variable Multiple Inheritance.
In this code I create person class
class person {
char name[20]; char lname[20];
public:
person() {}
person(char*n, char*ln);
virtual void print(ostream&o);
};
person::person(char*n, char*ln)
{
strcpy_s(name, 20, n);
strcpy_s(lname, 20, ln);
}
void person::print(ostream&o)
{
o << "name: " << name << " " << "last name: " << lname << endl;
}
ostream& operator<<(ostream&o, person&p)
{
p.print(o);
return o;
}
by Inheritance I create student and teacher class
class student : public virtual person
{friend class ststudent;
long str;
public:
student(char*n, char*ln, long s);
void print(ostream&o);
};
student::student(char*n, char*ln, long s) :person(n, ln), str(s) {}
void student::print(ostream&o)
{
person::print(o);
o << "st_num : " << str << endl;
}
class teacher : public virtual person
{
long salary;
public:
teacher(char*n, char*ln, long s);
virtual void print(ostream&o);
};
teacher::teacher(char*n, char*ln, long sal) :person(n, ln), salary(sal) {}
void teacher::print(ostream&o)
{
person::print(o);
o << "salary : " << salary << endl;
}
and in last class I use from Multiple Inheritance to create teacher assistant class but I don't know how to print the str and salary
class stteacher :public teacher, public student
{
public:
stteacher(char*n, char*ln, long st, long sa)
:student(0, 0, st), teacher(0, 0, sa), person(n, ln) {}
virtual void print(ostream&o);
};
void stteacher::print(ostream& o)
{
person::print(o);
o << str << salary;
}
I don't know how to do it. I can create two variables in stteacher class or change str and salary from private to public variable but I think I should do this with Multiple Inheritance.
Help me please.

Private data in a class cannot be accessed by any non-member, non-friend code. Period. Whether you use inheritance (or not) is irrelevant.
Thus, the only way for a different class to access that data is to:
Provide accessor function(s) so that callers can fetch the data. (If public, anyone can call it, but if it's a protected function then only derived classes gain access to it.)
Alternately, make the class(es) that need access a friend of the class. Friendship is something c++ programmers generally discourage, however, so only do so as a true last resort.
Change the access to the data to be public. (Very discouraged, as this defeats encapsulation entirely.)

A pattern for accessing private variables is to make a public function that returns that variable:
class teacher : public virtual person
{
long salary;
public:
teacher(char*n, char*ln, long s);
virtual void print(ostream&o);
long get_salary(void){return salary;}
};
Then the implentation for stteacher::print would be:
void stteacher::print(ostream& o)
{
person::print(o);
o << get_salary();
}
or something like this.

Classes by default are private, which means that anything before specifying access modifiers is private.
Private methods / local variables can only be accessed by the class that defined them and it's friend classes. In your case, to define a friend class you should first tell to student and teacher what stteacher is.
C++ reads your code from top to bottom, so if you want to use a variable/class/macro/whatever, you should declare it above it's use.
In code, this would look something like:
extern class stteacher; //You tell C++ that 'stteacher' is a class
class person {};
class student : public virtual person {
long str;
friend class stteacher; //You make stteacher a friend of student
public:
student(long str) : str(str) {}
};
class teacher : public virtual person {
long salary;
friend class stteacher; //You make stteacher a friend of teacher
public:
teacher(long salary) : salary(salary) {}
};
class stteacher : public student, public teacher {
public:
stteacher(long str, long salary) : student(str), teacher(salary) {}
void print() {
std::cout << "Salary: " << salary << "\nStr: " << str << std::endl;
}
}
int main() {
long str = 10, salary = 100;
stteacher(str, salary).print();
return 0;
}
Salary: 100
Str: 10
Eventhough this works, I suggest it would be best to use a more apropiate access modifier, such as protected.
protected stuff can be accessed by the class which defines it, it's friend classes AND classes which inherits it.
Using protected access modifiers, the above code would look like:
extern class stteacher; //You tell C++ that 'stteacher' is a class
class person {};
class student : public virtual person {
protected: //Can be accessed by it's childs
long str;
public:
student(long str) : str(str) {}
};
class teacher : public virtual person {
protected: //Can be accessed by it's childs
long salary;
public:
teacher(long salary) : salary(salary) {}
};
class stteacher : public student, public teacher {
public:
stteacher(long str, long salary) : student(str), teacher(salary) {}
void print() {
std::cout << "Salary: " << salary << "\nStr: " << str << std::endl;
}
}
int main() {
long str = 10, salary = 100;
stteacher(str, salary).print();
return 0;
}
Salary: 100
Str: 10

Related

trying to use inheritance but unable to access parent class

hello i am trying to create a class that uses inheritance from class Student to class Graduate Student but program says it is inaccessible.
class Student
{
Student(char* n, int id)
{
name = new char[strlen(n) + 1];
strcpy_s(name,strlen(n)+1, n);
studentId = id;
}
~Student()
{
if (name != NULL)
delete[]name;
}
void printStudent()
{
cout << "Student ID: " << studentId << "\nStudent Name: " << name << endl;
}
protected:
int studentId;
char* name;
};
class GraduateStudent :public Student
{
public:
GraduateStudent(char* n, char* a, int id) : Student(n, id)
{
area = new char[strlen(a) + 1];
strcpy_s(area, strlen(a) + 1, a);
}
~GraduateStudent()
{
if (area != NULL)
delete[]area;
}
void printGrad()
{
printStudent();
cout << "Research area: " << area << endl;
}
private:
char* area;
};
the program is supposed to print out an initiallised GraduateStudent class variable be calling printStudent();
Default access for a class is private, which makes OP's functions private.
So, your constructor is private.
You should read this.
Also, does this answer your question?
thx for edits #sweenish
When you are creating your classes, you may define access modifiers or access specifiers.(https://en.cppreference.com/w/cpp/language/access) (These are those words such as public, private or protected in your class). You may find [doc here]
class myClass{
public:
// public members go here
protected:
// protected members go here
private:
// private members go here
};
To make it simple, they allow you to tell whether a member should be accessible from everywhere, from derived classes only or not at all from outside the class where it is defined. When you do not put anything, in a C++ class, it means that it is private by default.
Thus your printStudent() method is private and cannot be accessed from your GraduateStudent class.
A good starting point for more details and more understanding of the notion is to read some tutorials
To solve your compilation problem, you should make your Student constructor, destructor and printStudent as public to allow the derived class to access them and compile.
class Student
{
public:
Student(char* n, int id)
{
...
}
~Student()
{
...
}
void printStudent()
{
...
}
....
};
You declared int studentId; and char* name; as protected, so in GraduateStudent you can access them, so you can easily do:
void printGrad() {
cout << "Student ID: " << studentId << "\nStudent Name: " << name << endl;
cout << "Research area: " << area << endl;
}
or, alternatively, declare printStudent(); in the public part of Student. In fact, if you declare something without any kind of specification, in a class, it is private by default, while in a struct, it is public.

C++ : Get a child member from the Father class

I recently asked a question related to the accessibility of a child member from a parent class using the cout method . But this time what if I want to use a get method instead of cout ? Will this change the idea ?
Assuming I have a class called CArray :
class CArray
{
public:
CArray();
private:
std::vector<CPerson *>Persons;
};
Where CPerson a parent class :
class CPerson
{
public:
CPerson();
virtual void Print()
{
std::cout << Name << "\n";
}
protected:
std::string Name;
};
and CStudent the child of Person
class CStudent : public CPerson
{
public:
CStudent();
private:
int MatriculationNr;
};
Let's assume that we loaded the private members of CStudent and CPerson as follows :
if (condition)
{
CStudent *S1 = new CStudent();
S1->load(src); //Load function is missing in class but ignore it
Persons.push_back(S1);
}
I recently learned how to access the private member of CStudent and CPerson with the use of the virtual method and exactly by adding to CStudent class this function below :
void Print()
{
CPerson::Print();
std::cout << MatriculationNr << "\n";
}
Now moving on to my class CArray . I wrote a print method to print the elements of Persons :
I just have to write Persons[i]->Print(); which will call Print() from all Persons .
The question now what If I want to get the MatriculationNr from the first element of Persons (as an example)?
cout << Persons[i]->getMatrikulNr();is not valid since we're trying here to get a function from a child class which is not possible this way .
I wanted to apply the same behavior that I did with print() but this is not possible due to the return parameter that I will have with the get method .
what If I want to get the MatriculationNr from the first element of Persons (as an example)?
You won't be able to. Not with the code you have shown, anyway. MatriculationNr exists only in CStudent, and it is private at that, so only CStudent can access it.
cout << Persons[i]->getMatrikulNr(); is not valid since we're trying here to get a function from a child class which is not possible this way . I wanted to apply the same behavior that I did with print() but this is not possible due to the return paramater that I will have with the get method .
You would have to either:
add a public virtual getMatrikulNr() method to CPerson which CStudent can then override, eg:
class CPerson
{
public:
...
virtual int getMatrikulNr() const
{
return 0;
}
...
};
class CStudent : public CPerson
{
public:
...
int getMatrikulNr() const override
{
return MatriculationNr;
}
private:
int MatriculationNr;
};
And then you can use Persons[i]->getMatrikulNr() as needed.
add a public getMatrikulNr() method to CStudent, and then dynamic_cast each CPerson* pointer to see if it is pointing at a CStudent object or not, eg:
class CStudent : public CPerson
{
public:
...
int getMatrikulNr() const
{
return MatriculationNr;
}
private:
int MatriculationNr;
};
CStudent *student = dynamic_cast<CStudent*>(Persons[i]);
if (student) {
// use student->getMatrikulNr() as needed...
}

How to access to superclass functions from a subclass object

Is there a way to access superclass methods from a subclass?
I made Apple class as a subclass of Fruit class, but I can not access to setName function in Fruit class from an object of Apple class.
Could you give me any advice?
#include <iostream>
#include <string>
using namespace std;
class Fruit {
public:
Fruit(string str)
{
cout << "Fruit class" << endl;
name = str;
cout << name << endl;
}
void setName(string str) {
name = str;
}
private:
string name;
};
class Apple:Fruit {
public:
Apple() :Fruit("apple"){
cout << "Apple class" << endl;
}
void setName(string str) {
name = str;
}
};
int main()
{
Apple apple;
apple.setName("Orange"); //I can not access to setName function from apple
return 0;
}
Use public inheritance like this:
class Apple : public Fruit
The default visibility for class is private if it's not specified. That is why you're not able to access the public members of the base class because they're now private due to their private visibility.
Contrary to a class, the default visibility for a struct is public i.e.:
struct Base {};
struct Derived : Base {}; // public inheritance
In your code, the overridden setName() method in the derived class is redundant as it cannot manipulate the private data member name directly. You'll have to use the base class method to set the name in your overridden method. As of now, you're not doing anything else in that method so you don't need it.
Here's your working code (live):
#include <iostream>
#include <string>
using namespace std;
class Fruit {
public:
Fruit(string str)
{
cout << "Fruit class" << endl;
name = str;
cout << name << endl;
}
void setName(string str) {
name = str;
}
private:
string name;
};
class Apple : public Fruit { // public inheritance
public:
Apple() :Fruit("apple"){
cout << "Apple class" << endl;
}
// void setName(string str) { // Redundant!
// name = str; // `name` is not accessible here!
// }
};
int main()
{
Apple apple;
apple.setName("Orange"); // Accessible here
return 0;
}
For more relevant information, refer to this:
Difference between private, public, and protected inheritance
Your Apple class is using private inheritance (the default when the type of inheritance is not specified), so all of Fruit's public methods are private in Apple and thus are not accessible for main() to call. You need to use public inheritance instead to fix that.
Also, there is no need to re-implement setName() in Apple. The inherited setName() from Fruit will suffice, once it is inherited as a public method in Apple.
class Apple : public Fruit {
public:
Apple() : Fruit("apple"){
cout << "Apple class" << endl;
}
};
Use public inheritance
class Apple:public Fruit
in class Default is Private
class Apple:Fruit
is same as
class Apple:private Fruit
You made private here, So you can not access member of Fruit by object of Apple even if it is public.
class Apple:public Fruit
{
public:
Apple() :Fruit("apple")
{
cout << "Apple class" << endl;
}
};
Or if you want it is to private use like this
class Apple:Fruit
{
public:
Apple() :Fruit("apple")
{
cout << "Apple class" << endl;
}
void setName(string str)
{
Fruit::setName(str);
}
};
First, change class Apple to
class Apple: public Fruit
then, use this method
apple.Fruit::setname()

Multiple Inheritance in C++ with 3 derived classes

I'm trying to use multiple inheritance. Person is my base class. Student and Angestellter inherit the protected attributes. WissenschaftlicheHilfskraft should also inherit these attributes (from Person, Student, Angestellter), but I can't call the method get_name() in my last derived class. Why?
#include <iostream>
using namespace std;
class Person {
protected:
string name;
public: //.......
string get_name() { name = "bob"; return name; }
};
class Student: public Person {
private: //......
public: //......
};
class Angestellte: public Person {
private: //......
public: //......
};
class WissenschaftlicheHilfskraft : public Student, public Angestellte
{
private: //......
public: //......
};
int main()
{
Person p;
cout << p.get_name() << endl; //WORKS
Student s;
cout << s.get_name() << endl; //WORKS
Angestellte a;
cout << a.get_name() << endl; //WORKS
WissenschaftlicheHilfskraft wh;
cout << wh.get_name() << endl; //DOESN'T WORK
return 0;
}
I want it to look like this:
Also, other than Paul R's answer your inheritance is wrong. You need to use virtual inheritance like as shown here.
class Student: public Person { becomes class Student: public virtual Person { and so on. This ensures that only one object of base is created for the final object.
This is the classic "diamond" problem with multiple inheritance. You can work around this by removing the ambiguity, e.g. change:
cout << wh.get_name() << endl; //DOESN'T WORK
to:
cout << wh.Student::get_name() << endl; //WORKS
However, see #Shiv's answer for a better solution which properly resolves the underlying problem.

C++ public method inherited from base class can not access private member variable in derived class

I have the code:
#include <iostream>
#include <cstdlib>
using namespace std;
class Animal{
private:
int age;
public:
Animal() : age(1) {}
void toString(){
cout << "Age: " << age << endl;
}
};
class Cat : public Animal
{
public:
Cat() : age(5) {}
/*
void toString(){
cout << "Age: " << age << endl;
}*/
private:
int age;
};
int main(){
Cat tom;
tom.toString();
system("pause");
return 0;
}
But when I run the program, the age of the tom variable is 1, not 5. Does the toString can not read the age variable? If we open the /* */ the toString method in the Cat class, the age will be 5 !
(My english is not good very much. Thanks)
The problem is that Cat is writing to the age variable in Cat, while toString() reads the age variable in Animal, which, with Animal's constructor, is initialized to 1.
To solve this, you can provide another constructor for Animal which accepts an age parameter which is used to initialize Animal's age member variable.
class Animal{
private:
int age;
public:
Animal() : age(1) {}
Animal(int param_age) : age(param_age) {} // Initialize member variable age with parameter
void toString(){
cout << "Age: " << age << endl;
}
};
class Cat : public Animal
{
public:
Cat() : Animal(5) {} // Call Animal's constructor that set's the age
};
UPDATE: Another solution is to add a setter method in Animal class that sets its age. You can then call it in Cat's constructor to set the proper age.
class Animal{
private:
int age;
public:
Animal() : age(1) {}
void setAge(int age) { this->age = age; }
void toString(){
cout << "Age: " << age << endl;
}
};
class Cat : public Animal
{
public:
Cat() {
setAge(5);
}
};
Yet another alternative is to make Animal's age member protected
class Animal{
protected: // THIS
int age;
public:
Animal() : age(1) {}
void toString(){
cout << "Age: " << age << endl;
}
};
And remove Cat's age variable in the class definition. Despite its simplicity, this approach gives you more risk in encountering the "brittle base class" problem. Thus, I recommend the former solution as it is less prone to the said problem, and IMHO better sticks to the "write against interfaces, not implementations" principle.
The problem is that you are setting Cat::age in the Cat constructor, not the Animal::age used by Animal::toString.
Change the visibility of Animal::age to protected.
class Animal {
protected:
int age;
public:
Animal() : age(1) {}
void toString(){
cout << "Age: " << age << endl;
}
};
Don't redeclare a second age (which becomes Cat::age). Instead, change the value of age (Animal::age).
class Cat : public Animal {
public:
Cat() {
age = 5;
}
};
Try:
#include <iostream>
#include <cstdlib>
using namespace std;
class Animal{
private:
int age;
public:
Animal(int a = 1) // Pass in the age as a parameter.
: age(a) // Default to 1.
{}
// Prefer generic print function rather than toString()
friend std::ostream& operator<<(std::ostream& s, Animal const& a) {
return s << "Age: " << a.age << '\n'; // Prefer '\n' rather than endl
// Unless you really want to flush
// the stream (this is not usually
// the case).
}
};
class Cat : public Animal
{
public:
Cat()
: Animal(5) // Now you can call the base class constructor
{} // And get it to set 5
private:
// int age; // don't have a private copy here.
// use the one that is available in the base class.
// Prefer generic print function rather than toString()
friend std::ostream& operator<<(std::ostream& s, Cat const& a)
{
// Print Cat
// Then use the Animal priting function to print more information about the object.
return s << "A Cat: " << static_cast<Animal const&>(*a);
}
};
int main(){
Cat tom;
// tom.toString(); // Don't use a toString() method.
// overload operator<< to print to a stream.
// If you want to convert to a string the just print
// to a string stream.
std::cout << tom;
system("pause");
return 0;
}