trying to use inheritance but unable to access parent class - c++

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.

Related

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 need to acces to private variable

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

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.

There's no error or warning displayed but my code won't run, it says console application stopped working

A basic application of inheritance on classes..Create a class Person which has derived classes Faculty and Student. Now derive class TA from classes Faculty and Student. Implement constructors and print function for each class.
#include<iostream>
#include<string>
using namespace std;
class person {
protected:
string name;
public:
person() {};
void setter(string x) {
name = x;
}
virtual void print() {
cout << "The name of faculty member is:" << name;
}
};
class faculty : public person {
public:
virtual void print() {
cout << "The name of faculty member is:" << name;
}
};
class student : public person {
public:
virtual void print() {
cout << "The name of student is:" << name;
}
};
class TA : public faculty, public student {
public:
virtual void print(string y) {
string nm = y;
cout << "The name of TA is:" << nm;
}
};
int main() {
person *p= NULL; faculty f; student stu; TA t;
p->setter("Anna");
p = &f;
p->print();
p = &stu;
p->print();
faculty *fac = &t;
fac->print();
t.print("Bob");
return 0;
}
In main, you are creating a pointer to a person and initializing that pointer to null: person *p= NULL
You then immediately dereference that null pointer: p->setter("Anna");
Also, judging by some of your wording, it sounds like you are using Visual Studio. If that's the case, running the application through VS should jump straight to debug mode when you crash like this. You can then look at the current state of the program and figure out why you crashed.
The following does not allocate an instance of a person:
person *p= NULL;
It only created a pointer, and set the pointer to what ever NULL is currently defined as.
You probably meant to do something more like:
person* p = new person;
Here, the new allocates space in the dynamic memory, and invokes the ctor of that class.
With p set to NULL (whatever NULL currently is),
p-><some method of p>
references a non-existent person instance at memory address 0. If that method tries to use any data attributes of the instance, on most common systems, that data access (near the very important addr 0) will trigger a fault.

C++ how to declare a vector of objects as a member of a class

I'm trying to declare a vector<Item> as a private member of another class Inventory, but it is giving me an error saying that Item is not in scope. Both classes are declared in the same file. I don't know how to change the scope that it looks at or whatever you are supposed to do to make it work.
Here is the code to make absolutely clear what I'm trying to do.
class Inventory {
public:
private:
vector<Item> inventory;
};
class Item {
public:
void SetName(string nm)
{ name = nm; };
void SetQuantity(int qnty)
{ quantity = qnty; };
void SetPrice(int pric)
{ price = pric; };
virtual void Print()
{ cout << name << " " << quantity << " for $" << price
<< endl; };
virtual ~Item()
{ return; };
protected:
string name;
int quantity;
int price;
};
Item must be defined before its usage as a template argument.
Technically, you may be able to get away with a forward declaration in specific contexts, but to save you time and frustration with learning the exact rules, it is easier to just make sure you have defined it first.
In general, the order of declarations are important. If you use a type in the declaration of another type, the used type must already be defined. Exceptions to this rule involve usage by pointer and reference which only require forward declaration.
As std::vector<Item> is a type in its own right, it must be declared after the declaration of the Item class.
(It's similar to the rule that for class Child : public Base, the declaration of Base needs to appear above that line).
A forward declaration is not insufficient.
One way round this is to use a std::vector<std::shared<Item>> (a vector of smart pointers) but that, of course, changes the structure of the vector. In that case a forward declaration is sufficient.
Define Item first, then Inventory.
class Item {
public:
void SetName(string nm)
{ name = nm; };
void SetQuantity(int qnty)
{ quantity = qnty; };
void SetPrice(int pric)
{ price = pric; };
virtual void Print()
{ cout << name << " " << quantity << " for $" << price
<< endl; };
virtual ~Item()
{ return; };
protected:
string name;
int quantity;
int price;
};
class Inventory {
public:
private:
vector<Item> inventory;
};