-1

I'm new to c++ and I was trying to develop my skills through solving challenges on Hacker Rank.

This is the challenge I was working on https://www.hackerrank.com/challenges/virtual-functions

My solution for the challenge is

class Person {
protected: 
    int age;
    string name;

public:
    virtual void getdata() {
    }   
    virtual void putdata() {
    }       
};

class Student: public Person{
protected: 
    int marks[6];
    int sum = 0;
    static int cur_id2;

public:
    void getdata() {
        cin >> name >> age;

        for(int i = 0; i < 6; i++) {
            cin >> marks[i] ;
            sum = sum + marks[i];
        } 
    }    
    void putdata() {
        cout << name <<" "<< age<<" " << sum <<" "<< cur_id2 << endl;
    } 
    Student() {
        cur_id2++;
    }
};

int Student::cur_id2 = 0;

class Professor: public Person {
protected: 
    int publications;
    static int cur_id1; 

public: 
    void getdata() {
        cin >> name >> age >> publications;
    }
    void putdata() {
        cout << name <<" "<< age <<" "<< publications<<" " << cur_id1 << endl;
    }  

    Professor() {
        cur_id1++;  
    }
};

int Professor::cur_id1 = 0;

I got those results :

Your Output 

Walter 56 99 2
Jesse 18 403 2
Pinkman 22 135 2
White 58 87 2

Expected Output

Walter 56 99 1
Jesse 18 403 1
Pinkman 22 135 2
White 58 87 2

I think the problem with the id is that in the main function it always gets data for all objects before it prints it this mean that the id variable will always get the last value after creating the last object so I think this way will not make sense I need another way to assign an id for each new instance of the class and keep it somewhere in order to use it when the putdata function is called . I thought of using an array to keep all ids but I don't think it's the right way to solve this problem please help me. Thank you

Edit:

Thank you all your answers helped me solving the challenge I just modified small pieces of code

 protected: 
   int publications;
   static int next_id1; 

  int cur_id1; 




  Professor(){

        cur_id1=++next_id1;  
    }

};int Professor::next_id1=0;

And the same in the Student class.

Iman
  • 9
  • 5

6 Answers6

2

It appears that you want to assign a unique ID value to each Student and to each Professor. To do this, you need two variables:

  1. A class variable static int next_id; which keeps track of the next ID to use.

  2. A member variable int id; which is assigned a value for each object based on next_id.

I suggest that you read about what static means in this context.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • Thank you it really helps I understand static variables but I haven't thought of using two variables instead of one. – Iman Jul 15 '17 at 23:50
  • @Iman The key here is to realize that there are two pieces of data to keep track of: 1. the next id, which is shared by all instances of the class and 2. the id of a specific object, which belongs to each object. Glad I can help. Good luck with learning more coding! – Code-Apprentice Jul 16 '17 at 02:00
2

It looks like you need to spend some time reading up on static data members (for example here). Essentially, if a member of a class is declared static then exactly one value of that member exists in your program -- all instances of that class share the same static members and they can be accessed both with (myClassInstance.StaticMember) and without an instance (MyClass::StaticMember).

So think about how you can use this together with non-static members to solve your problem.

JMAA
  • 1,730
  • 13
  • 24
  • That's what I was looking for.I should have thought of using a non-static variable with the static one. Thanks It helps. – Iman Jul 15 '17 at 23:52
0

I solved this challenge by the following way (showing just the Professor class):

class Professor : public Person {
public:
    Professor() : Person(), publications(0), cur_id(++key) {
    }
    virtual void getdata() {
        std::cin >> name >> age >> publications;
    }
    virtual void putdata() {
        std::cout << name << ' ' << age << ' ' << publications
                  << ' ' << cur_id << std::endl;
    }
private:
    int publications;
    int cur_id;
    static int key;
};
int Professor::key = 0;

In my example I've used the a static class variable to keep track of the number of instances. This variable is the same for all instances, so when one instance change it, the other will see the change. The cur_id is a member variable which is initialized in the constructor and won't be changed by the other instances.

Akira
  • 4,385
  • 3
  • 24
  • 46
0

This short program should show the behavior of static member variables within classes.

#include <vector>
#include <string>
#include <iostream>
#include <iomanip>
#include <map>
#include <fstream>

class Person {
protected:
    // sbcp = static base class Person
    static unsigned sbcPID_;
    const unsigned  myID_ { sbcPID_ };

    std::string name_;
    unsigned age_;

public:
    Person() { ++sbcPID_; }
    Person( const std::string& name, unsigned age ) :
        name_( name ), age_( age ) {
        ++sbcPID_;
    }

    static unsigned getBaseStaticID() { return sbcPID_; }
    virtual unsigned getMyID() const { return this->myID_; }

    std::string getName() const { return name_; }
    unsigned getAge() const { return age_; }

    virtual void getdata() { std::cout << "Person::getDataCalled\n"; /* code */  }
    virtual void putdata() { std::cout << "Person::putDataCalled\n"; /* code */ }
};

class Student : public Person {
private:
    // sdcS = static derived class Student
    static unsigned sdcSID_;
    const unsigned myID_ { sdcSID_ };

    int marks[6] {};
    int sum { 0 };

public:
    Student() : Person() { ++sdcSID_; }
    Student( const std::string& name, unsigned age ) :
        Person( name, age ) {
        ++sdcSID_;
    }


    static unsigned getDerivedStaticID() { return sdcSID_; }
    virtual unsigned getMyID() const override { return this->myID_; }

    virtual void getData() { std::cout << "Student::getDataCalled\n"; /* code */ }
    virtual void putData() { std::cout << "Student::putDataCalled\n"; /* code */ }
};

class Professor : public Person {
private:
    // sdcP = static derived class Proffesor
    static unsigned sdcPID_;
    const unsigned myID_ { sdcPID_ };

    int publications_;

public:
    Professor() : Person() { ++sdcPID_; }
    Professor( const std::string& name, unsigned age ) :
        Person( name, age ) {
        ++sdcPID_;
    }

    static unsigned getDerivedStaticID() { return sdcPID_; }
    virtual unsigned getMyID() const override { return this->myID_; }

    virtual void getData() { std::cout << "Professor::getDataCalled\n"; /* code */ }
    virtual void putData() { std::cout << "Professor::putDataCalled\n"; /* code */ }
};

unsigned Person::sbcPID_ = 0;
unsigned Student::sdcSID_ = 0;
unsigned Professor::sdcPID_ = 0;

int main() {
    std::vector<Professor*> professors;
    std::vector<Student*>   students;

    std::multimap<unsigned, Person*> allCampusMembers;

    // Populate a staff of 5 professors;
    std::vector<std::string> professorsNames { "D. Hall", "T. Roland", "S. McKinney", "A. Wesker", "J. Krispen" };
    std::vector<unsigned>    professorAges { 39, 58, 27, 69, 42 };

    for ( unsigned n = 0; n < 5; n++ ) {
        professors.emplace_back( new Professor( professorsNames[n], professorAges[n] ) );
        // Also add to our map
        allCampusMembers.emplace( std::make_pair( professors[n]->getMyID(), dynamic_cast<Person*>(professors[n]) ) );
    }

    // Do the Same for 10 students
    std::vector<std::string> studentNames { "M. Asbury", "D. Brighton", "L. Caldwell", "R. Griscom", "B. Koloski",
                                            "J. Martin", "V. Ottaman", "A. Peterson", "S. Richards", "A. Samuels" };
    std::vector<unsigned> studentAges { 22, 21, 19, 20, 23,
                                        26, 28, 32, 19, 21 };

    for ( unsigned n = 0; n < 10; n++ ) {
        students.emplace_back( new Student( studentNames[n], studentAges[n] ) );
        // Also add to our map
        allCampusMembers.emplace( std::make_pair( students[n]->getMyID(), dynamic_cast<Person*>(students[n]) ) );
    }

    // Also log to a text file:
    std::fstream out( "Log.txt", std::ios::out | std::ios::trunc );

    // Use The Map To Go Through And Print Out The (Person ID), (Private ID), Name & Age.
    std::multimap<unsigned, Person*>::iterator it = allCampusMembers.begin();

    for ( ; it != allCampusMembers.end(); ++it ) {
        out << "BaseID: " << it->second->getBaseStaticID() << " "
            << "DerivedID: " << it->second->getMyID() << "\n"
            << "Name: " << it->second->getName() << " "
            << "Age: " << it->second->getAge() << "\n\n";

        std::cout << "BaseID: " << it->second->getBaseStaticID() << " "
            << "DerivedID: " << it->second->getMyID() << "\n"
            << "Name: " << it->second->getName() << " "
            << "Age: " << it->second->getAge() << "\n\n";
    }
    std::cout << std::endl;

    // Clear Out Our Memory
    allCampusMembers.clear();
    for ( unsigned n = 0; n < professors.size(); n++ ) {
        delete professors[n];
        professors[n] = nullptr;    
    }
    professors.clear();

    for ( unsigned n = 0; n < students.size(); n++ ) {
        delete students[n];
        students[n] = nullptr;
    }
    students.clear();

    professorsNames.clear();
    professorAges.clear();
    studentNames.clear();
    studentAges.clear();

    std::cout << "\nPress any key and enter to quit." << std::endl;
    char c;
    std::cin >> c;

    return 0;
}

If you run this short program as is; you should get this as output:

BaseID: 15 DerivedID: 0
Name: D. Hall Age: 39

BaseID: 15 DerivedID: 0
Name: M. Asbury Age: 22

BaseID: 15 DerivedID: 1
Name: T. Roland Age: 58

BaseID: 15 DerivedID: 1
Name: D. Brighton Age: 21

BaseID: 15 DerivedID: 2
Name: S. McKinney Age: 27

BaseID: 15 DerivedID: 2
Name: L. Caldwell Age: 19

BaseID: 15 DerivedID: 3
Name: A. Wesker Age: 69

BaseID: 15 DerivedID: 3
Name: R. Griscom Age: 20

BaseID: 15 DerivedID: 4
Name: J. Krispen Age: 42

BaseID: 15 DerivedID: 4
Name: B. Koloski Age: 23

BaseID: 15 DerivedID: 5
Name: J. Martin Age: 26

BaseID: 15 DerivedID: 6
Name: V. Ottaman Age: 28

BaseID: 15 DerivedID: 7
Name: A. Peterson Age: 32

BaseID: 15 DerivedID: 8
Name: S. Richards Age: 19

BaseID: 15 DerivedID: 9
Name: A. Samuels Age: 21

As this will show you that static member variables are used more as a reference count where a const is used for a unique id value.

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
0

It's one another easier method for done this program.......

class Person
{
protected:
  int age;
  string name;
public:
      virtual void getdata(){};
      virtual void putdata(){};
};
class Professor : public Person
{
    int publication;
    static int id1;
      public:
       void getdata()
       {
           cin>>name;
           cin>>age;
           cin>>publication;
       }
       void putdata()
       {
          cout<<name<<" "<<age<<" "<<publication<<" "<<id1<<endl;
          id1++;
       }
};
int Professor::id1=1;
class Student : public Person
{
    int marks[6];
     static int id2;
  public:
      int sum=0;
   void getdata()
   {
       cin>>name;
       cin>>age;
       for(int i=0;i<=5;i++)
       {
          cin>>marks[i];
          sum=sum+marks[i];
       }
   }
   void putdata()
   {
      cout<<name<<" "<<age<<" "<<sum<<" "<<id2<<endl;
      id2++;
   }
};
int Student::id2=1;
0

I solved this way :

class Person
{
    public :

    string name;
    int age;
    virtual void getdata() =0;
    virtual void putdata() =0;

};

class Professor : public Person 
{
    private :
    static int id1;
    int publications;
    public :
    void getdata()
    {
        cin>>name>>age>>publications;
    }
    void putdata()
    {
        cout<<name<< " "<<age<<" "<<publications<<" "<<id1<<endl;
        id1++;
    }
};

int Professor::id1=1;
class Student : public Person
{
    private :
    static int id2;
    int marks[6];
    int sum=0;

    public :
    void getdata()
    {
        cin>>name>>age;
        for(int i=0;i<6;i++)
        {
            cin>>marks[i];
            sum=sum+marks[i];
        }
    }
    void putdata()
    {
        cout<<name<< " "<<age<<" "<<sum<<" "<<id2<<endl;
        id2++;
    }
};
int Student::id2=1;