miatech
miatech

Reputation: 2278

need help with object oriented program in Visual C++

guys, I have the following code, but I'm getting error at compiling time... the error is at the end. Thanks 1st Class is "Person"

#ifndef PERSON_H//protecting .h files
#define PERSON_H//protecting .h files
#include <iostream>
#include <string>
using namespace std;

class Person
{
public:
    Person();
    Person(string first, string last)
    {
        firstName = first;
        lastName = last;
    }
    virtual void setName(string first, string last)
    {
        firstName = first;
        lastName = last;
    }
    virtual void setWeightAge(int w, int a)
    {
        weight = w;
        age = a;
    }
    virtual string getFirstName()
    {
        return firstName;
    }
    virtual string getLastName()
    {
        return lastName;
    }
    virtual int getWeight()
    {
        return weight;
    }
    virtual int getAge()
    {
        return age;
    }
    virtual void printPerson()
    {
        cout << "Name: " << firstName << " " << lastName << endl;
        cout << "Age: " << age << endl;
        cout << "Weight: " << weight << endl;
    }
protected:
    string firstName, lastName;
    int weight, age;
};
#endif

2nd Class is "Student"

#ifndef STUDENT_H//protecting .h files
#define STUDENT_H//protecting .h files
#include <iostream>
#include <string>
#include "Person.h"
using namespace std;

class Student : public Person
{
public: 
    Student();
    Student(Person s)
    {
        sStudent = s;
    }
    virtual void setGPA(double g)
    {
        gpa = g;
    }
    virtual void setSchedule(string c, string t, string d)
    {
        stClass = c;
        time = time;
        days = d;
    }
    virtual void setGrade(char g)
    {
        grade = g;
    }
    virtual double getGPA()
    {
        if (grade == 'a') { gpa = 4.0; }
        if (grade == 'b') { gpa = 3.0; }
        if (grade == 'c') { gpa = 2.0; }
        else gpa = 0;
        return gpa;
    }
    virtual char getGrade()
    {
        return grade;
    }

    virtual void printSchedule()
    {
        cout << "Class | Days | Time " << endl;
        cout << stClass << " | " << days << " | " << time << endl;
    }
protected:
    string stClass, time, days;
    char grade;
    double gpa;
    Person sStudent;
};
#endif

and Main()

#include <iostream>
#include "Student.h"
using namespace std;

int main()
{
    //creating a person
    Person john("John", "Smith");
    john.setWeightAge(180, 39);
    john.printPerson();

    //making john a student
    Student johnStdntMath(john);
    johnStdntMath.setSchedule("Math", "7:45", "M, W");
    johnStdntMath.setGrade('b');
    johnStdntMath.printPerson();
    johnStdntMath.printSchedule();

    system("pause");
    return 0;

errors:

1>------ Build started: Project: Person, Configuration: Debug Win32 ------
1>  main.cpp
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Person::Person(void)" (??0Person@@QAE@XZ) referenced in function "public: __thiscall Student::Student(class Person)" (??0Student@@QAE@VPerson@@@Z)
1>c:\users\jorge\documents\visual studio 2010\Projects\Person\Debug\Person.exe : fatal error LNK1120: 1 unresolved externals
}

Upvotes: 0

Views: 1178

Answers (4)

D.Shawley
D.Shawley

Reputation: 59633

You are accessing the no argument constructor for Person when you create the johnStdntMath instance. You need to either

  1. Implement Person::Person() or ...
  2. Change Student::Student(Person s) to Student::Student(Person const& s)

There are some other problems in your code as well. Student is-a Person so there is no need for the Student class to have a Person member variable - it shares the instance variables of its base class by virtue of inheritance. In other words, Student extends Person so your program could be written:

int main() {
    Student johnStdntMath;
    johnStdntMath.setName("John", "Smith")
    johnStdntMath.setWeightAge(180, 39);
    johnStdntMath.setSchedule("Math", "7:45", "M, W");
    johnStdntMath.setGrade('b');
    johnStdntMath.printPerson();
    johnStdntMath.printSchedule();
    return 0;
}

I would also avoid the using namespace std; statement anywhere and especially in a header file. For example, your Student class contains a member variable named time. This will conflict with the std::time_t std::time(std::time_t*) function defined in <ctime> if that header is included before "student.h".

Upvotes: 1

Sid Zhang
Sid Zhang

Reputation: 972

You haven't implement the default constructor Person(),you can write it like this:

Person():weight(0)
        ,age(0){};

If you just want to complier it, this is enough;
Here are some tips below:
1.Check your mind, does class Student really need a Person member. If you really need it, Student(Person) may add an explicit symbol:

explicit Student(const Person& s) : sStudent(s) {...};  

2.In Person.h

  protected:
        string firstName, lastName;
        int weight, age;

the protected may be private?

Upvotes: 0

wilhelmtell
wilhelmtell

Reputation: 58725

Listen to your linker, it's just as it says: In constructor Student::Student(Person) you're referring to constructor Person::Person(), but you didn't define Person::Person(), not in a way the linker can see when it does its thing with the Student constructor.

Technically, because you are filling in sStudent in the Student constructor's body the compiler first default-initializes the Person object sStudent, and then assigns to it s, the Person parameter of the constructor. If you'd use the initializer list then the Person member wouldn't be default-initialized and then assigned to but rather copy-constructed right away:

Student(const Person& s) : sStudent(s) { }

But the question remains: Why are you publicly declaring a default constructor in Person and not define it?

Also, you have a leak in Student. The string and Person members of Student won't clean up because when a Student object destructs its destructor won't be called. The Person destructor will be called, but not the Student destructor, and the reason being that the destructor of Person is non-virtual.

One more thing: It's a bad idea in object-oriented design in general and C++ in particular to use inheritance for reuse. The reason is that this very often leads to a violation of the LSP. It can also bear a (not major but nonetheless) performance overhead for introducing a virtual table. But it's the correctness that suffers that matters when you pick inheritance when you should really be using delegation.

Upvotes: 1

Pablo
Pablo

Reputation: 8644

I suggest you double check your is-A and has-A relationships.

Writing Student : public Person says that a Student is-A Person. But later, you have a member variable sStudent of type Person, which says a Student has-A Person, and I'm guessing is not what you really want.

Check out the answers to this question: Inheritance vs. Aggregation for better explanations.

Upvotes: 3

Related Questions