簡體   English   中英

需要有關Visual C ++中的面向對象程序的幫助

[英]need help with object oriented program in Visual 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
}

我建議您仔細檢查您的is-A和has-A關系。

寫作Student : public Person說學生是一個人。 但是后來,您有了一個Person類型的成員變量sStudent ,它說一個Student有一個Person,而我猜這不是您真正想要的。

查看以下問題的答案: 繼承與聚合,以獲得更好的解釋。

聽您的鏈接器,就像它說的那樣:在構造函數Student::Student(Person)您所指的是構造函數Person::Person() ,但您並未以某種方式定義Person::Person()鏈接器可以看到它何時使用Student構造函數執行操作。

從技術上講,由於您是在Student構造函數的主體中填充sStudent ,因此編譯器首先默認初始化Person對象sStudent ,然后為其分配 s ,即構造函數的Person參數。 如果您要使用初始化列表,那么Person成員將不會被默認初始化,然后被分配給它,而是立即進行復制構造:

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

但是問題仍然存在:為什么要在Person公開聲明默認構造函數而不定義它?

另外,您還有Student泄漏。 StudentstringPerson成員不會清除,因為當Student對象破壞其析構函數時將不會被調用。 將調用Person析構函數,但不會調用Student析構函數,其原因是Person的析構函數是非虛擬的。

還有一件事:使用繼承進行重用對於一般的面向對象設計(尤其是C ++)來說是一個壞主意。 原因是,這經常導致違反LSP 對於引入虛擬表,它也可能承擔(雖然不是主要的,但主要的)性能開銷。 但是,當您應該真正使用委托時選擇繼承時,所遭受的正確性才是最重要的。

創建johnStdntMath實例時,您正在訪問Personno參數構造函數。 你需要

  1. 實現Person::Person()或...
  2. Student::Student(Person s)更改為Student::Student(Person const& s)

您的代碼中還有其他一些問題。 Student 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的成員變量。 如果<ctime>定義的std::time_t std::time(std::time_t*)函數與"student.h"之前包含該標頭,則這將發生沖突。

您尚未實現默認的構造函數Person() ,可以這樣編寫:

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

如果您只是想編譯它,那就足夠了;
以下是一些提示:
1.檢查一下您的想法,上課的Student真的需要一個Person成員Person 如果您確實需要, Student(Person)可以添加一個explicit符號:

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

2.In Person.h

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

protected可能是private

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM