I am currently learning Inheritance. The code below works just fine.
#include <iostream>
class Student {
protected:
double GPA = 3.12;
};
class Employee {
protected:
int Salary = 1500;
};
class TeachingAssistant: public Student, public Employee {
public:
void Print() {
std::cout << GPA << " " << Salary << "\n";
}
};
int main() {
TeachingAssistant TA;
TA.Print();
}
However this code below does NOT work.
#include <iostream>
class Student {
protected:
double GPA = 3.12;
};
class Employee: public Student {
protected:
int Salary = 1500;
};
class TeachingAssistant: public Student, public Employee {
public:
void Print() {
std::cout << GPA << " " << Salary << "\n";
}
};
int main() {
TeachingAssistant TA;
TA.Print();
}
The Error
I only changed one thing in between these two code snippets and it's the addition of "public Student" next to the class Employee. What did I do wrong? Please explain this using simple words/logic.
Field GPA can be accessed from class TeachingAssistant by two ways:
TeachingAssistant -> Student
TeachingAssistant -> Employee -> Student
You must specify which one you need
For example:
std::cout << Employee::GPA << " " << Salary << "\n";
Another solution is to remove the other inheritance of class Student:
class TeachingAssistant: public Employee {
public:
void Print() {
std::cout << GPA << " " << Salary << "\n";
}
};
Your situation is the following: you have a teaching assistant who's an Student (1) and Employee (2) - however the Employee based on your design is also a student. You end up by having teaching assistant being two students and one employee. C++ is telling which student's you want me to print the GPA for, hence the ambiguous.
The design is simply wrong in the second code snippet.
TeachingAssistant is both an Employee and a Student: Yes.
An
Employee is a Student: No.
Related
#include <iostream>
using namespace std;
class Student
{
protected:
long studentID;
public:
void setStudentID(long s_){ studentID = s_; }
Student(): studentID(0){}
long get_StudentID(){ return studentID; }
};
class Exam : public Student
{
protected:
float mark;
public:
void setMark(float m_){ mark = m_; }
Exam(): mark(0){}
float getMark(){ return mark; }
};
class Sports : public Student
{
protected:
float score;
public:
void setScore(float s_){ score = s_; }
Sports(): score(0){}
float getScore(){ return score; }
};
class Result: public Student, public Exam, public Sports
{
private:
float Total;
public:
float getTotal(){ return getMark() * getScore(); }
void display();
};
void Result::display()
{
cout << "Student ID = " << get_StudentID() << endl;
cout << "Exam Mark = " << getMark() << endl;
cout << "Sports Score = " << getScore() << endl;
cout << "Total Mark = " << getTotal();
}
int main()
{
Result st1;
st1.display();
return 0;
}
I wrote this code in Code::Blocks and it's incomplete yet , but this error that says "refrence to get_StudentID is ambigous" confused me; What's wrong with it?
Should I delete using namespace and insert std:: before all (cout, cin & endl) statments?
You are misunderstanding inheritance. For example, the class Exam with this line
class Exam : public virtual Student
is publicly inheriting from Student. Public inheritance should only be used in an IS-A relationship. In this case, Exam is not a Student so you shouldn't use public inheritance. Same goes for Sports.
"Call is ambiguous" means that when you call get_StudentID from Result the compiler can't decide between Exam::get_StudentID or Sports::get_StudentID which they both inherit from Student.
Instead:
Remove the inheritance, don't use inheritance anywhere here. I would completely remake this and make a Student class with Exam and Sports member objects (which can become vector of objects later if needed) and call the needed functions from the member objects instead. As a general tip, avoid multiple inheritance unless completely necessary.
This is an easy fix
remove Student from Results base class
make Student public virtual from both Exam and Sports class
#include <iostream>
using namespace std;
class Student
{
protected:
long studentID;
public:
void setStudentID(long s_){ studentID = s_; }
Student(): studentID(0){}
long get_StudentID(){ return studentID; }
};
class Exam : public virtual Student
{
protected:
float mark;
public:
void setMark(float m_){ mark = m_; }
Exam(): mark(0){}
float getMark(){ return mark; }
};
class Sports : public virtual Student
{
protected:
float score;
public:
void setScore(float s_){ score = s_; }
Sports(): score(0){}
float getScore(){ return score; }
};
class Result: public Exam, public Sports
{
private:
float Total;
public:
float getTotal(){ return getMark() * getScore(); }
void display();
};
void Result::display()
{
cout << "Student ID = " << get_StudentID() << endl;
cout << "Exam Mark = " << getMark() << endl;
cout << "Sports Score = " << getScore() << endl;
cout << "Total Mark = " << getTotal();
}
int main()
{
Result st1;
st1.display();
return 0;
}
Godbolt: https://godbolt.org/z/4f5n8M5of
I am new to programming and just shifted to C++ from C.
I was learning the concepts of inheritance and tried to make a simple application that takes input from the user and show that data on consol, But I am facing some problems running it.
My program seems syntactically correct but it crashes frequently. So I wondered if anyone can teach me what to take into consideration while writing the program to prevent those crashes.
here is my sample code
/*
Define a class Hospital having rollno and name as data members and member function to
get and print data.
Derive a class Ward from class Hospital having data members: ward number and member function to get and print data.
Derive another class Room from Hospital having data member bed number and nature of illness and member function to get and print data.
Derive class Patient from Class Ward and Class Room.
In main () declare 5 object of Class Patient and get and display all the information.
Use the concept of Virtual Base Class and Hybrid Inheritance.
*/
#include <iostream>
#include <string>
using namespace std;
class Hospital
{
int rollno;
string name;
public:
void get()
{
cout << "Enter the roll number : ";
cin >> rollno;
fflush(stdin);
cout << "Enter the name :";
fflush(stdin);
getline(cin, name);
fflush(stdin);
}
void print()
{
cout << "\nRoll No : " << rollno;
cout << "\nName : " << name;
}
};
class Ward : public virtual Hospital
{
int W_number;
public:
void get()
{
// Hospital :: get();
cout << "Enter the Ward number : ";
cin >> W_number;
}
void print()
{
cout << "\nWard number : " << W_number;
}
};
class Room : virtual public Hospital
{
int bedNumber;
string natureOfIllness;
public:
void get()
{
cout << "Enter the bed number of patient : ";
cin >> bedNumber;
fflush(stdin);
cout << "Enter the nature of illness : ";
fflush(stdin);
getline(cin, natureOfIllness);
}
void print()
{
cout << "\nBed Number : " << bedNumber;
cout << "\nNature of illness : " << natureOfIllness;
}
};
class Patient : public Ward, public Room
{
public:
void get()
{
Hospital::get();
Ward::get();
Room::get();
}
void print()
{
cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
Hospital::print();
Ward::print();
Room::print();
cout << "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
}
};
int main()
{
Patient p[5];
for (int i = 0; i < 5; i++)
{
cout << "\n\nEnter informtion of patient " << i + 1 << endl;
p[i].get();
}
for (int i = 0; i < 5; i++)
{
cout << "Informtion of patient " << i + 1 << endl;
p[i].print();
}
return 0;
}
thank you.
When you inherit from a class you need to make the destructor virtual
So Hospital should have a virtual destructor.
If you want to override functions declare them virtual in the base class
virtual void get();
virtual void print();
otherwise you are hiding the functions/
Always initialize all member variables
Just write
class Ward : public Hospital {...}
But the fundamental problem with your code is that using Hospital as base
class doesn't make sense, a Ward is not a kind of Hospital
You should instead treat the Hospital as a container, so called composition.
The Hospital contains one or more wards so use Hospital as the container, containing a Wards have Rooms, Rooms have Patients,
Now if you want to have the same behavior in all your classes you could create an interface for get/set for instance and use that instead to inherit from.
struct IGetPrint
{
virtual void get() = 0;
virtual void print() = 0;
~IGetPrint() = default;
};
class Hospital : public IGetPrint
{
public:
void get() override
{
std::cout << "Enter the roll number : ";
std::cin >> rollno;
std::cout << "Enter the name :";
std::getline(std::cin, name);
}
void print() override
{
std::cout << "\nRoll No : " << rollno;
std::cout << "\nName : " << name << std::flush;
}
protected:
int rollno{0};
std::string name;
};
// side note, do not use fflush(stdin) use cin.ignore instead
// otherwise you will undefined behavior
try using void main() instead of int main and end it with getch() with using #include<stdlib.h>
it might help you out
sometimes I used to face this type of problem and got sorted by doing that
So I have these classes:
In main I wrote an array of pointers:
student *arry[10];
How can I make each cell point to an object of a different class?
For example :
I want the cell 0 , 2 , 4
point to an object of class medstudent
using ( new statement )
thank you
here is class medStudent
#include<iostream>
#include"student.cpp"
using namespace std;
class medStudent:public student {
public :int clinicH;
public:
medStudent(int ch, string n , int i ):student(n,i){
setClinicH(ch);
cout << "New Medecine Student" << endl;
}
~medStudent(){
cout << "Medecine Student Deleted" << endl;
}
medStudent(medStudent & ms):student(ms){
cout << "New Copy Medecined Student" << endl;
}
medstudent(){
}
void setClinicH(int ch){
clinicH = ch;
}
int getClinicH()const{
return clinicH;
}
void print()const{
student::print();
cout << "Clinical Hours: " << getClinicH() << endl;
}
};
Here is class student:
#include <iostream>
//#include"medstudent.cpp"
using namespace std;
class student//:public medstudent
{
public :
static int numberOfSaeeds;
const int id;
string name;
public:
~student(){
cout << "Delete Student: " << getName() << " " << endl ;
}
student(string n, int i):id(i){
setName(n);
cout << "Student with args" << endl ;
}
void setName(string n){
name = n;
}
string getName()const{
return name;
}
void print()const{
cout << "My name is: " << name << endl;
cout << "My ID is: " << id << endl;
}
void setNOS(int nos){
numberOfSaeeds = nos;
}
int getNOS(){
return numberOfSaeeds;
}
void printAddress()const{
cout << "My address is " << this << endl;
}
student * getAddress(){
return this;
}
student(student & sc):id(sc.id){
name = sc.name;
setName(sc.getName());
cout << "New Object using the copy constructor" << endl;
}
};
Here is main code:
#include<iostream>
using namespace std;
#include"time.cpp"
#include "student.cpp"
//#include"medstudent.cpp"
int main(){
student a1("asa" , 2);
student * a[10];
a[3]= new student("jj", 22 );
a[0] = new medStudent();
}
Since you explicitly declare a medStudent constructor the compiler will not create a default constructor for your class. And when you do new medStudent(); you are (explicitly) trying to invoke the default constructor, which doesn't exist.
That will give you a build error, one that should have been very easy to diagnose if you read it and most importantly shown it to us (when asking questions about build errors, always include the complete and unedited error output, including any informational output, in the body of the question, together with the code causing the error).
The solution? Call the existing parameterized constructor. E.g. new medStudent("foo", 123).
By the way, if you want inheritance to work okay, and the base-class destructor to be called when deleting an object of a child-class, then you need to make the destructors virtual.
I'm trying to figure out basic inheritance. But I seem unable to get the enum to take. It just responds with a smiley face and nothing.
I honestly don't know what I'm doing wrong so I'm afraid I'll have to just throw all my code at you.
#include <iostream>
#include <string>
using namespace std;
enum Discipline {
COMPUTER_SCIENCE, Computer_SCIENCE_AND_INNOVATION
};
const string DISCIPLINE_STRINGS[2] = { "Computer Science",
"Computer Science and Innovation",
};
class Person {
public:
Person(){cout << "Person object created using the default Person constructor\n";};
Person(const string& name, Discipline type){pName = name; pType = type;};
~Person(){cout << "Person object destroyed\n";};
string pName;
string pType;
};
class Faculty: public Person {
public:
Faculty();
Faculty(const string& name, Discipline type) {pName = name; pType = type; cout << "Faculty object created using the alternative Faculty constructor\n";};
~Faculty(){cout << "Faculty object destroyed!";};
string getName(){return pName;};
string getDepartment(){return pType;};
};
class Student: public Person {
public:
Student();
Student(const string& name, Discipline type) {pName = name; pType = type; cout << "Student object created using the alternative Student constructor\n";};
~Student(){cout << "Student object destroyed!";};
string getMajor(){return pType;};
string getName(){return pName;};
};
int main()
{
Faculty prof("Name1", COMPUTER_SCIENCE);
Student stu(" Name2", Computer_SCIENCE_AND_INNOVATION);
cout << endl << "I, " << stu.getName() << ", am majoring in " << stu.getMajor() << "." << endl;
cout << "I am taking CSI 240 with Prof. " << prof.getName() << ", who teaches "
<< prof.getDepartment() << " courses." << endl << endl;
system ("pause");
return 0;
}
You are printing out the enum instead of the actual string.
You should use the enum to index into DISCIPLINE_STRINGS.
When you set the type string do this:
pType = DISCIPLINE_STRINGS[type]
I have been working on multiple inheritance. I have made a program but it keeps giving me an error such as Human::getInfo is ambiguous. How do I solve the problem
here is my code
#include <iostream>
#include <string>
using namespace std;
class Man{
protected:
std::string name;
public:
void getInfo(string hName){
name = hName;
}
void showInfo(){
std::cout << "Your name is: " << name << std::endl;
std::cout << "And you are a MAN" << std::endl;
}
};
class Women:public Man{
public:
Women(){}
void Women_showInfo(){
std::cout << "Your name is: " << name << std::endl;
std::cout << "And you are a Women" << std::endl;
}
};
class Human:public Women, public Man{
public:
Human(){}
};
int main(){
//local variables
string choice;
string name;
//class object
Human person;
//user interface
cout << "What your name: " ;
cin >> name;
cout << "Are you a [boy/girl]: ";
cin >> choice;
//saving name
person.getInfo(name); //ambiguous
//if handler
if (choice == "boy"){
person.showInfo(); //ambiguous
}else if(choice == "girl"){
person.Women_showInfo(); //works fine no error
}
system("pause");
return 0;
}
Also feel free to make changes in my code and would be even better if your could point out my mistake using my code.
Your design is rather questionable, but the particular ambiguity arises because Human inherits from both Woman and Man, but Woman already inherits from Man.
So Human has two getinfo() functions in it - Human::Man::getinfo() and Human::Woman::Man::getinfo(). Unless you tell the compiler which one to use it doesn't know, and thus reports an error.