在Visual C ++中需要面向对象程序的帮助

时间:2011-02-17 02:26:58

标签: c++

伙计们,我有以下代码,但是我在编译时遇到错误......错误结束了。谢谢 第一类是“人”

#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

第二课是“学生”

#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

和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;

错误:

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
}

4 个答案:

答案 0 :(得分:3)

我建议你仔细检查你的is-A和has-A关系。

Student : public Person说学生是一个人。但是后来,你有一个sStudent类型的成员变量Person,它表示学生有一个人,我猜你不是你想要的。

查看此问题的答案:Inheritance vs. Aggregation以获得更好的解释。

答案 1 :(得分:1)

聆听你的链接器,就像它说的那样:在构造函数Student::Student(Person)中你指的是构造函数Person::Person(),但你没有定义Person::Person(),而不是在某种程度上链接器可以看到它何时使用Student构造函数。

从技术上讲,因为您在sStudent构造函数体中填充Student,编译器首先默认初始化Person对象sStudent,然后分配< / em>到它s,构造函数的Person参数。如果您使用初始化列表,那么Person成员将不会默认初始化,然后分配给,而是立即复制构建:

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

但问题仍然存在:为什么你公开声明Person中的默认构造函数而不定义它?

此外,Student发生泄密。 string的{​​{1}}和Person成员将无法清除,因为当Student对象析构其析构函数时将不会被调用。将调用Student析构函数,但不会调用Person析构函数,原因是Student的析构函数是非虚拟的。

还有一件事:对于面向对象的设计而言,这是一个坏主意,特别是C ++使用继承来重用。原因是这经常导致违反LSP。它还可以承担引入虚拟表的(不是主要的,但仍然是)性能开销。但是当你真正使用委托时,选择继承时,这是正确的。[/ p>

答案 2 :(得分:1)

在创建Person实例时,您正在访问johnStdntMath无参数构造函数。你需要

  1. 实施Person::Person()或......
  2. Student::Student(Person s)更改为Student::Student(Person const& s)
  3. 您的代码中还存在其他一些问题。 Student is-a Person所以Student类不需要Person成员变量 - 它可以凭借其共享基类的实例变量继承。换句话说,Student扩展Person,因此可以编写您的程序:

    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;
    }
    

    我也会在任何地方避免使用using namespace std;语句,特别是在头文件中。例如,您的Student类包含名为time的成员变量。如果在std::time_t std::time(std::time_t*)之前包含该标头,则会与<ctime>中定义的"student.h"功能冲突。

答案 3 :(得分:0)

您尚未实现默认构造函数Person(),您可以这样写:

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

如果你只是想要编译它,这就足够了;
以下是一些提示:
1.检查你的想法,班级Student确实需要Person成员。如果您确实需要,Student(Person)可能会添加explicit符号:

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

2.在Person.h

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

protected可能是private