5

継承を扱う課題があります。

Manager() と Intern() が継承する Employee() の基本クラスがあります。

私のインストラクターは私たちに次の指示を与えました:

main() で、スタッフ ポインターの配列を宣言し、次のレコードに初期化します。

Manager("IT", 100, "MF1", "ML1")
Manager("HR", 50, "MF2", "ML2")
Intern("SIUE", 0, "IF1", "IL1")
Intern("SLU", 0, "IF2", "IL2")

次に、ループして配列を表示する必要があります。彼が例として提供する出力は、子クラスに関連する特定の情報が出力されたため、 Manager() および Intern() toString() メソッドが呼び出されたに違いないことを示しています。ただし、配列にアクセスするときは、子へのポインターではなく、従業員のポインターを取得します。彼が提供したスクリーンショットを添付しました。

私の出力がどのように見える必要があるかのスクリーンショット

どうすればこれを達成できるのかわかりません。

スタッフ配列の宣言は次のとおりです。

Employee * staff = new Employee[4];

Manager() オブジェクトへのポインターを格納できません。何らかの方法がない限り、これをぶら下げることができます:

staff[0] = new Manager("IT", 100, "MF1", "ML1");

私の唯一のオプションは、このようなことをしているようです(これを1行で行うにはどうすればよいですか?):

Employee * e = new Manager("IT", 100, "MF1", "ML1");
staff[0] = *e;

しかし、明らかに今私がこれを行うとき:

cout << staff[0].toString();

子クラスではなく、基本クラスの Employee() toString() メソッドを取得します。

関連する場合に備えて、Employee() と Manager() の次の 2 つのクラス定義を次に示します。

class Employee{

private:
    int eid;
    string firstName;
    string lastName;

public:
    Employee();
    Employee(int eid, string fname, string lname);
    void setEID(int eid);
    void setFirstName(string fname);
    void setLastName(string lname);
    int getEID();
    string getFirstName();
    string getLastName();
    virtual string toString();
};


class Manager : public Employee, IPayable{

private:
    string department;

public:
    Manager();
    Manager(string dept, int eid, string fname, string lname);
    double pay();
    void setDepartment(string d);
    string getDepartment();
    string toString();
};

そして、これが私が2つのtoString()メソッドを実装すると仮定した方法で、従業員toString()がManager()toString()内に埋め込まれています。

string Employee::toString(){
    return "{eid = " + std::to_string(getEID()) + ", firstName = " + getFirstName() + ", lastName = " + getLastName() + "}";  
}

string Manager::toString(){
    return "Manager{" + Employee::toString() + ", department = " + getDepartment() + ", salary = " + std::to_string(pay()) +"}";
}
4

5 に答える 5

3

必要なのは、ポインターの配列です。

Employee *staff[4];

これで、従業員にポインタを割り当てることができます。したがって、従業員の子へのポインタを割り当てることができます。

staff[0] = new Manager("IT", 100, "MF1", "ML1");

そして、あなたは従業員の関数を呼び出すことができます:

staff[0]->toString();
于 2013-02-21T02:14:38.563 に答える
2

これが1つの方法です:

Manager manager1("IT", 100, "MF1", "ML1");
Manager manager2("HR", 50, "MF2", "ML2");
Intern intern1("SIUE", 0, "IF1", "IL1")
Intern intern2("SLU", 0, "IF2", "IL2")

Employee *staff[4] = {
  &manager1,&manager2,&intern1,&intern2
};
于 2013-02-21T02:15:33.390 に答える
2
typedef std::unique_ptr<Employee> EmployeePtr;
typedef std::array<EmployeePtr,4> Employees;
Employees employees =
{
    new Manager("IT", 100, "MF1", "ML1"),
    new Manager("HR", 50, "MF2", "ML2"),
    new Intern("SIUE", 0, "IF1", "IL1"),
    new Intern("SLU", 0, "IF2", "IL2")
};

保存されます。他に何がありましたか?アクセス方法。

employees[0]->toString();

終わり。

于 2013-02-21T02:19:51.977 に答える
1

Manager思いもよらないオブジェクトへのポインタを保存できません

はい、できます。または、少なくとも、型Employee*のオブジェクトを指す型のポインタを持つことができますManager。結局のところ、Managers Employees(これはあなたの継承が言うことです)なので、それは理にかなっています。

toString()関数はとしてマークされvirtual、その実装をオーバーライドするため、型のポインターを介してManager型のオブジェクトで呼び出されると、の特殊な実装が選択されます。ManagerEmployee*Manager

一方、以下はコンパイルされません(オブジェクト値をポインター値に割り当てています)。

staff[0] = *e;

だから、それを試してはいけません。代わりに、これを使用してください:

staff[0] = new Manager(...);
...
staff[0]->toString();

delete最後に、生のポインタを使用する場合は、スコープ外になる前に忘れないでください。そうしないと、メモリリークが発生します。実際、オブジェクトの存続期間を自動的に処理するスマートポインタの使用を検討する必要があります。

于 2013-02-21T02:16:26.833 に答える
1

あなたのクラスは配列ではなく継承にあるようですので、ベクトルを使用します..

std::vector<Employee*> staff;

staff.push_back(new Manager);
staff.push_back(new Intern);

Employeeこれで、ポインターでいっぱいの配列ができました。のtoString()メソッドEmployeeは仮想であるため、割り当てた各ManagerおよびInternオブジェクトのメンバー メソッドが呼び出されます。

staff[0]->toString(); // Manager toString()
staff[1]->toString(); // Intern toStrin()

完了したら、メモリを解放することを忘れないでください。

于 2013-02-21T02:26:37.900 に答える