C++ Inheritance not taking an enum - c++

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]

Related

c++ inheritance problem and pointers. Trying to access child class with a pointer but the function is not being able to be found

So I am coding in c++ and am having a problem with inheritance and pointers. I am trying to access how many notches are in the gun slinger object (gun) but it is saying person has no such function. gun is a child class of person so I am a bit confused. here is the code
side note the error is p->getnotches() in main and it says (class "Person" has no member "getnotches")
int main()
{
Person *p;
Gunslinger gun("Doc Holiday", 5);
//PokerPlayer poker("Billy Jack");
//BadDude bad("Billy Kid", 4);
Person p1("James Cagney");
cout << "Persons name is: " << p1.getName() << endl;
Person p2 = p1;
Person p3, p4;
p4 = p3 = p1;
p = new Person("Jack Benny");
cout << "Person name is: " << p->getName() << endl;
cout << "Person 1 name is: " << p1.getName() << endl;
cout << "Person 2 name is: " << p2.getName() << endl;
cout << "Person 3 name is: " << p3.getName() << endl;
cout << "Person 4 name is: " << p4.getName() << endl;
delete p;
p = &gun;
cout << "Gunslinger name: " << p->getName() << " and number of notched on gun is: " <<
p->getnotches() << endl;
return 0;
}
#ifndef PERSON_H
#define PERSON_H
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Person
{
private:
char *name;
public:
Person();
Person(string name);
virtual string getName();
virtual ~Person();
};
#endif
// no default constructor
Person::Person()
{
}
// this function assigns a name to person object
Person::Person(string n)
{
name = new char[n.length() + 1];
strcpy(name, n.c_str());
}
// this functions grabs the name of the person object
string Person::getName()
{
return name;
}
Person::~Person()
{
delete[] name;
}
#ifndef GUNSLINGER_H
#define GUNSLINGER_H
#pragma once
#include "Person.hpp"
#include <cstring>
#include <string>
class Gunslinger : public Person
{
private:
char *name;
int notches;
double drawTime;
public:
Gunslinger(string n, int cylinders);
int getnotches();
virtual string getName();
~Gunslinger();
};
#endif
#include "Gunslinger.hpp"
Gunslinger::Gunslinger(string n, int clinders)
{
name = new char[n.length() + 1];
strcpy(name, n.c_str());
notches = clinders;
}
string Gunslinger::getName()
{
return name;
}
int Gunslinger::getnotches()
{
return notches;
}
Gunslinger::~Gunslinger()
{
delete[] name;
}
In this expression
p->getnotches()
the static type of the pointer p is Person * due to this declaration
Person *p;
So the compiler searches in the class Person the function getnotches and does not find it because the class does not have such a function.
class Person
{
private:
char *name;
public:
Person();
Person(string name);
virtual string getName();
virtual ~Person();
};
You need to use dynamic_cast (if the compiler supports it) or reinterpret_cast with the pointer.
Although you have a Gunslinger object, you're treating it as a Person object and the Person class does not have a getnotches method. I'm not sure why you want to have a Person* to a Gunslinger object. Just use the Gunslinger 'gun' instead of the Person* 'p'.
cout << "Gunslinger name: " << gun.getName() << " and number of notched on gun is: " <<
gun.getnotches() << endl;

Why is casting from base to derived giving this functionality?

I am confused as to why casting a derived class to a pointer of base class calls upon the derived class method when I haven't used the virtual keyword. Is this normal behavior? Doesn't the pointer hold a Person object in memory, therefore casting it to a Student should not have any affect to its contents?
class Person {
public:
Person()
{
cout << "Creating Person Class" << endl;
}
void about_me()
{
cout << "I am a person" << endl;
}
};
class Student : protected Person {
public:
Student()
{
cout << "Creating Student Class" << endl;
}
void about_me()
{
cout << " I am a student " << endl;
}
};
int main()
{
Person* pperson = new Person();
Student* pstudent = new Student();
pperson->about_me();
pstudent->about_me();
pperson-> about_me();
((Student*)pperson)-> about_me(); // this is the line where I do the cast
return 0;
}
The output of the code is the following
Creating Person Class
Creating Person Class
Creating Student Class
I am a person
I am a student
I am a person
I am a student
Your code "works" because neither of your about_me() methods access their respective this pointers for anything.
Technically speaking, what you are doing is undefined behavior, because pperson does not point at a valid Student object, but you are telling the compiler to treat it as if it were. So literally anything can happen.
In many common compiler implementations, a class method call like pperson->about_me() is actually calling more like about_me(pperson), where about_me() gets implemented as a standalone function with a this input parameter. So code you have shown might be implementation by the compiler more like this under the hood (not exactly, but you should get the idea):
struct Person
{
};
void Person_Person(Person *this)
{
cout << "Creating Person Class" << endl;
}
void Person_about_me(Person *this)
{
cout << "I am a person" << endl;
}
struct Student
{
};
void Student_Student(Student *this)
{
Person_Person(this);
cout << "Creating Student Class" << endl;
}
void Student_about_me(Student *this)
{
cout << " I am a student " << endl;
}
int main()
{
//Person* pperson = new Person();
byte *buf1 = new byte[sizeof(Person)];
Person* pperson = (Person*) buf1;
Person_Person(pperson);
//Student* pstudent = new Student();
byte *buf2 = new byte[sizeof(Student)];
Student* pstudent = (Student*) buf2;
Student_Student(pstudent);
//pperson->about_me();
Person_about_me(pperson);
//pstudent->about_me();
Student_about_me(pstudent);
//pperson-> about_me();
Person_about_me(pperson);
//((Student*)pperson)-> about_me();
Student_about_me((Student*)pperson);
return 0;
}
So, in the 4th call to about_me(), you are instructing the compiler to call Student::about_me() instead of letting it call Person::about_me() normally, with its this parameter set to a Person* pointer that is type-casted to Student*. Since this is not dereferenced by about_me(), the call is "successful" in that you see the "expected" output. It doesn't matter what this points to in this case, because it is not being used.
Now, try adding some data members to your classes, and then output those members in about_me(), and you will see very different, very unexpected/random results, due to the undefined behavior you are invoking. For example:
class Person
{
protected:
string m_name;
public:
Person(const string &name)
: m_name(name)
{
cout << "Creating Person Class" << endl;
}
void about_me()
{
cout << "I am a person, my name is " << m_name << endl;
}
};
class Student : protected Person
{
private:
int m_id;
string m_school;
public:
Student(const string &name, int id, const string &school)
: Person(name), m_id(id), m_school(school)
{
cout << "Creating Student Class" << endl;
}
void about_me()
{
cout << "I am a student, my name is " << m_name << ", my id is " << m_id << " at " << m_school << endl;
}
};
int main()
{
Person* pperson = new Person("John Doe");
Student* pstudent = new Student("Jane Doe", 12345, "Some School");
pperson->about_me(); // "I am a person, my name is John Doe"
pstudent->about_me(); // "I am a student, my name is Jane Doe, my id is 12345 at Some School"
pperson->about_me(); // "I am a person, my name is John Doe"
((Student*)pperson)->about_me(); // runtime error!
delete pstudent;
delete pperson;
return 0;
}
Live Demo

arry of pointers ( classes )

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.

Why won't my point in Species class point to its heterogeneous class

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.

C++ class multiple inheritance error

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.