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
Related
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.
#include <iostream>
using namespace std;
class CSE
{
private:
char Name;
double Roll;
public:
void getN(char N, double RN)
{
Name = N;
Roll = RN;
}
};
char EnterName()
{
cout << "Enter the name of the student" << ;
}
char EnterRN()
{
cout << "enter the rn" << ;
};
int main()
{
CSE nnn;
nnn.getN(N, RN);
cout << "enter the name" << nnn.EnterName << endl;
cout << "enter the roll" << nnn.EnterRN << endl;
return 0;
}
What should I correct here for the right implementation of my code? I just want to keep the names and roll number private and then public them afterwards. I also want to enter the name and roll number by the user and then display it.
You are defining (free) functions instead declaring and defining a method:
class CSE {
...
public:
char EnterRN();
};
char CSE::EnterRN() {
...
}
If you want to do it inline then the closing } of the class needs to be after those functions.
My code consists of a class animal and 2 sub classes inheriting animal charactistics - amphibian, and fish. The code compiles but the oorder of the deconstructors kills them from bottom to top but i want them to be killed from top to bottom as the display function order suggests-
Here is my code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Animal{
public:
Animal(string name, string diet, bool queue)
: name_species(name), regime(diet), queue(queue){
if(name == ""){cout << "Error, name can't be empty!" << endl; }
else { cout << "A new animal" << endl; }}
virtual ~Animal(){ cout << "End of animal" << endl; }
virtual void display()const;
protected:
string name_species;
string regime;
bool queue;
};
void Animal::display() const{
cout << "I present the species " << name_species << endl;
}
class Fish : public Animal {
public:
Fish(string name, unsigned int scales, string diet = "Carnivore", bool queue = true)
: Animal(name, diet, queue), scales(scales){ cout << "Add a fish" << endl; }
~Fish(){ cout << "Fish species " << name_species << " is turned off. " << endl; }
void display() const override;
private:
unsigned int scales;
};
void Fish::display() const {
Animal::display();
if(queue == true){cout << "I have a tail "; }
else { cout << "I don't have a tail "; } cout << "and i follow " << regime << endl;
cout << "I have " << scales << " scales" << endl;
}
class Amphibian : public Animal {
public: Amphibian(string name, string diet, unsigned int claws = 4, bool queue = false)
: Animal(name, diet, queue), claws(claws){ cout << "Add an amphibian" << endl; }
void affiche() const;
~Amphibian(){ cout << "Amphibian species " << name_species << " is turned off. " << endl; }
private:
unsigned int claws;
};
void Amphibian::display() const {
Animal::display();
if(queue == true){ cout << "I have a tail "; }
else { cout << "I don't have a tail " ; } cout << "and i follow " << regime << endl;
cout << "I have " << scales << " scales " << endl;
}
class Species {
public:
virtual void display()const = 0;
virtual ~Species();
private:
vector<Animal*> animals;
};
void Species::display()const{
for(size_t i(0); i < animals.size(); ++i){
animals[i]->display(); }
}
Species::~Species(){
for(size_t i(0); i < animals.size(); ++i){
delete animals[i];
}
}
int main()
{
Amphibian kermit("lizard", "insects");
Fish nemo("dolphin", 6);
Fish sala("salamander", 4);
Animal* animal(&kermit);
animal->display();
animal = &nemo;
animal->display();
return 0;
}
Nothing inherits from class Species so conversion not possible using assignment technique.
There are no methods in Species to convert an Animal into a Species, so no luck there. Compiler running out of ideas on how to convert Animal to Species.
Looks like Species is a container of Animals. You will need to supply a method that adds an Animal to the container inside Species or make the container public.
You want something like this:
Species s;
s.animals.push_back(&kermit);
The following code suggests that you see Species as something more general than Animal:
Species* animal(&kermit);
animal->display();
animal = &nemo;
In this case you shall make sure the inheritance is declared, by changing the class definition to :
class Animal : Species {
...
};
Some remarks nevertheless:
as all species have a name, whether vegetal or animal, you could consider to move member Animal::name_species to class Species;
the fact that the name of the class Species is in plural, that you have a vector as member, and that every element of this member is displayed or deleted when the corresponding operation is called for the member tends however to suggest that Species is an aggregation of Animals. It is then not clear how you add elements to your vector.
Rather than using raw pointers in the aggregation, you could use shared_ptr instead. You then don't need to delete the aniamls yourself.
I use Borland C++ 4.5 as my school recommends it.
When I try to run this code, I get three errors when I try to run the code.
I try to change the access specifier every time, but I fail.
#include "iomanip.h"
#include "iostream.h"
#include <conio.h>
#include <stdio.h>
class person
{
public:
int code;
char name[50];
void PEnter()
{
cout << "\nEnter Code :\n";
cin >> code;
cout << "\nEnter Name :\n";
gets(name);
}
};
class account : public person
{
public:
float pay;
void AcEnter()
{
cout << "\nEnter Pay :\n";
cin >> pay;
}
};
class admin : public person
{
public:
int experience;
void AdEnter()
{
cout << "\nEnter Experience :\n";
cin >> experience;
}
};
class master : public account, admin
{
public:
void MEnter()
{
PEnter();
AcEnter();
AdEnter();
}
void MRet()
{
cout << setw(20) << name << "\t" << setw(7) << code << "\t"
<< setw(6) << pay << "\t" << setw(3) << experience << "\n";
}
};
void main()
{
clrscr();
master M[200];
int i = 0;
char ch;
do {
M[i].MEnter();
++i;
cout << "\nEnter More :\n";
cin >> ch;
} while (ch == 'Y' || ch == 'y');
int j = i;
clrscr();
cout << setw(20) << "Name\t" << setw(7) << "Code\t" << setw(6)
<< "Pay\t" << setw(3) << "\tExperience\n";
for (i = 0; i <= j; ++i) {
M[i].MRet();
}
getch();
}
These are the three errors that I get:
Error NONAME00.CPP 43 : Member is ambiguous 'person::PEnter' and 'person::PEnter' in function master::MEnter()
Error NONAME00.CPP 49 : Member is ambiguous 'person::name' and 'person::name' in function master::MRet()
Error NONAME00.CPP 49 : Member is ambiguous 'person::code' and 'person::code' in function master::MRet()
I do not know whether the class person is being inherited or not (by the master class).
You hit the diamond inheritance problem. What it is and how to solve it described here virtual inheritance Note inheritance in the wiki example is very close to yours so there should not be any problem for you to follow solution provided there
One can also inherit the base class as virtual
class admin : public virtual person
class account : public virtual person
call the fn as
person::PEnter();
input the value like this -
person::name;
person::code;
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.