c++ - 防止对象切片 - C++

标签 c++

我正在尝试创建 Person 对象的 vector 。然而,我真的想存储从 Person 基类派生的 Adult、Professor 和 Student 对象。询问后this question我了解到我的问题在于对象拼接,它会将派生类保存为 Person 类,因为这就是 vector 的内容。我尝试修改代码来纠正这种情况,但我仍然遇到一些错误,需要一些额外的帮助。谢谢!

这是我的 main.cpp 代码:

#include "Person.h"
#include "Professor.h"
#include "Student.h"
#include "Adult.h"
#include <vector>
#include <string>
#include <iostream>
using namespace std;

template<typename T> void addPerson(vector<Person *> &personVector) {
    cout << "DEBUG" << endl;
    personVector.push_back(new T());
}

void addFriend(vector<Person *> &personVector) {
    bool loop = true;
    while (loop) {
        cout << "\nWhich Person would you like to create? " << endl;
        cout << "  1. Professor" << endl;
        cout << "  2. Student" << endl;
        cout << "  3. Adult" << endl;
        int caseVar;
        cin >> caseVar;
        switch (caseVar) {
        case 1: 
            addPerson<Professor>(personVector);
            // old incorrect line: addPerson<Professor *>(personVector);
            loop = false;
            break;
        case 2: 
            addPerson<Student>(personVector);
            // old incorrect line: addPerson<Student *>(personVector);
            loop = false;
            break;
        case 3: 
            addPerson<Adult>(personVector); 
            // old incorrect line: addPerson<Adult *>(personVector);
            loop = false;
            break;
        default: cout << "Unknown Entry Please Try Again." << endl;
        }
    }
}

void displayFriends(vector<Person *> &personVector) {
    if (personVector.size() > 1) {
        for (unsigned i = 0; personVector.size() > i; i++)
            cout << i+1 << ". " << personVector[i]->getName() << endl;
            cout << "DEBUG" << endl;
    }
}

void viewFriend(vector<Person *> &personVector) {
    if (personVector.size() > 1) {
        displayFriends(personVector);
        cout << "Which # friend would you like to view? ";
        int num;
        cin >> num;
        personVector[num-1]->coutPerson();
    } else if (personVector.size() == 1) {
        personVector[0]->coutPerson();
    } else {
        cout << "No friends to View." << endl;
    }
}


void deleteElementFromArray(int element, vector<Person *> &personVector) {
    vector<Person *> newPersonVector;
    for (unsigned i = 0; personVector.size() > i; i++)
        if (i != element - 1)
            newPersonVector.push_back(personVector[i]);
    personVector = newPersonVector;
}

void removeFriend(vector<Person *> &personVector) {
    if (personVector.size() > 1) {
        displayFriends(personVector);
        cout << "Which # friend would you like to remove? ";
        unsigned num;
        cin >> num;
        if (num <= personVector.size())
            deleteElementFromArray(num, personVector);
        else
            cout << "Invalid Selection" << endl;
    } else if (personVector.size() == 1) {
        cout << "Removed one and only friend" << endl;
    } else {
        cout << "No friends to Remove." << endl;
    }
}


int main() {
    vector<Person *> personVector;
    // Run Main Menu
    cout << "Friends with Stuff" << endl;
    cout << "Adding 5 friends to the list" << endl;
    personVector.push_back(new Person("James"));
    personVector.push_back(new Person("Martin"));
    personVector.push_back(new Person("Sammi"));
    personVector.push_back(new Person("Donny"));
    personVector.push_back(new Person("Ronald"));
    bool loop = true;
    while (loop) {
        cout << "\nWhat would you like to do? " << endl;
        cout << "  1. Add New Friend" << endl;
        cout << "  2. View Friend" << endl;
        cout << "  3. Remove Friend" << endl;
        cout << "  4. Clear Friends" << endl;
        cout << "  5. Get Object" << endl;
        cout << "  6. Exit" << endl;
        int caseVar;
        cin >> caseVar;
        switch (caseVar) {
        case 1: 
            addFriend(personVector);
            break;
        case 2: 
            viewFriend(personVector);
            break;
        case 3: 
            removeFriend(personVector);
            break;
        case 4: 
            personVector.clear();
            break;
        case 5:

            break;
        case 6: 
            loop = false; 
            break;
        default: cout << "Unknown Entry Please Try Again." << endl;
        }
    }
}

我收到以下错误

InitializeBuildStatus:
1>  Touching "Debug\FPVisualStudio.unsuccessfulbuild".
1>ClCompile:
1>  main.cpp
1>\\cs1\cs_students\mlindahl15\cs172\final project\fpvisualstudio\main.cpp(12): error C2664: 'void std::vector<_Ty>::push_back(_Ty &&)' : cannot convert parameter 1 from 'Professor **' to 'Person *&&'
1>          with
1>          [
1>              _Ty=Person *
1>          ]
1>          Reason: cannot convert from 'Professor **' to 'Person *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>          \\cs1\cs_students\mlindahl15\cs172\final project\fpvisualstudio\main.cpp(26) : see reference to function template instantiation 'void addPerson<Professor*>(std::vector<_Ty>)' being compiled
1>          with
1>          [
1>              _Ty=Person *
1>          ]
1>\\cs1\cs_students\mlindahl15\cs172\final project\fpvisualstudio\main.cpp(12): error C2664: 'void std::vector<_Ty>::push_back(_Ty &&)' : cannot convert parameter 1 from 'Student **' to 'Person *&&'
1>          with
1>          [
1>              _Ty=Person *
1>          ]
1>          Reason: cannot convert from 'Student **' to 'Person *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>          \\cs1\cs_students\mlindahl15\cs172\final project\fpvisualstudio\main.cpp(30) : see reference to function template instantiation 'void addPerson<Student*>(std::vector<_Ty>)' being compiled
1>          with
1>          [
1>              _Ty=Person *
1>          ]
1>\\cs1\cs_students\mlindahl15\cs172\final project\fpvisualstudio\main.cpp(12): error C2664: 'void std::vector<_Ty>::push_back(_Ty &&)' : cannot convert parameter 1 from 'Adult **' to 'Person *&&'
1>          with
1>          [
1>              _Ty=Person *
1>          ]
1>          Reason: cannot convert from 'Adult **' to 'Person *'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>          \\cs1\cs_students\mlindahl15\cs172\final project\fpvisualstudio\main.cpp(34) : see reference to function template instantiation 'void addPerson<Adult*>(std::vector<_Ty>)' being compiled
1>          with
1>          [
1>              _Ty=Person *
1>          ]
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:02.90
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

我相信它告诉我代码中的指针太多。但是我不明白为什么会出现这种情况。我唯一有指针的地方是 vector 包含我需要在每种情况下重复的 vector 。并且需要这些指针,因此我没有对象切片。

Person.h

#ifndef PERSON_H
#define PERSON_H
#include <string>
#include "Date.h"
#include "PhoneNumber.h"
using namespace std;

class Person
{
protected:
    string name;
    Date birthday;
    PhoneNumber phoneNumber;
    string city, state;
public:
    // Constructors
    Person();
    Person(string name) { 
        this->name = name; 
        birthday = Date();
        phoneNumber = PhoneNumber("0000000000");
        city = "Unknown";
        state = "Unknown";
    }
    // Getter and Setter Methods
    string getName();
    void setName(string);
    Date getBirthday();
    // Methods
    void coutPerson();
};
#endif

人物.cpp

#include "Person.h"
#include "PhoneNumber.h"
#include "Date.h"
#include <string>
#include <iostream>
using namespace std;

// Constructors
Person::Person() {
    cin.ignore();
    cout << "Name? ";
    getline(cin, name);
    cout << "Birthday: " << endl;
    birthday.askUserForDate();
    phoneNumber.create();
    cout << "City? ";
    getline(cin, city);
    cout << "State? ";
    getline(cin, state);
}

// Getter and Setter Methods
string Person::getName() {
    return name;
}

void Person::setName(string name) {
    this->name = name;
}

void Person::coutPerson() {
    cout << name << endl;
    birthday.coutDate();
    phoneNumber.coutPhoneNumber();
    cout << city << ", " << state << endl;
}

// Methods

学生.h

#ifndef STUDENT_H
#define STUDENT_H
#include "Person.h"
using namespace std;

class Student : public Person
{
private:
    string dorm;
    int dormRoom;
public:
    // Constructors
    Student();
    Student(Student &);
    // Getter and Setter Methods

    // Methods
    void coutPerson();
};
#endif

学生.cpp

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

// Constructors
Student::Student() {
    cin.ignore();
    cout << "Dorm? ";
    getline(cin, dorm);
    cout << "Dorm Room #? ";
    cin >> dormRoom;
}

// TODO Copy Constructors
// TODO Deconstructors
// Overload < > ==

Student::Student(Student &student) {
    Person::Person(student);
    dorm = student.dorm;
    dormRoom = student.dormRoom;
}

void Student::coutPerson() {
    cout << "DEBUG: Student::coutPerson()" << endl;
    Person::coutPerson();
    cout << "Dorm Room: " << this->dorm << " " << this->dormRoom << endl;
}

// Methods

最佳答案

您的模板参数是指针,但不应该在您的方法中,例如template<typename T> void addPerson(...)您创建 T 的新实例使用new因此,您创建了一个指向人员的新指针(即 new Person*() ,这将导致 Person*** )。

因此,只需这样调用它:addPerson<Professor>(personVector);这将改变new T()进入new Professor()从而产生 Professor*结果。

另一件事:

void deleteElementFromArray(int element, vector<Person *> personVector) {
  vector<Person *> newPersonVector;
  for (unsigned i = 0; personVector.size() > i; i++)
    if (i != element - 1)
        newPersonVector.push_back(personVector[i]);
    personVector = newPersonVector;
}

首先,您要删除 element - 1因此请注意,您不能传递 0(即 element 此处是基于 1 的索引)。

其次,您分配 newPersonVector到参数personVector 。但是,由于您按值传递 vector (它是复制的),因此更改在该函数之外将不可见。

对此您有几种解决方案:

  1. personVector 中删除该项目而不是复制那些不应该删除的内容。使用类似 personVector.erase(personVector.begin() + element) 的内容为此(请注意,这里的语法可能不太正确,但您应该明白)。
  2. 传递一个指向 vector 的指针:void deleteElementFromArray(int element, vector<Person *>* personVector)
  3. 返回新 vector 并替换旧 vector 。该调用因此变为 personVector = removeFriend(personVector);

我个人更喜欢选项 1,因为它重用了 vector ,从而减少了复制操作。

关于c++ - 防止对象切片 - C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8397644/

相关文章:

c++ - C++11 中默认的正则表达式引擎是什么?

c++ - 关联容器中 std::array data() 失效的风险?

iphone - 关于xcode中浮点值的问题

c++ - 使用 QtConcurrentRun 和 mutex 的非常简单的方法有时会出现段错误

c++ - 如何暂停执行,直到用户登录Win32上的启动应用程序

C++浮点到特定长度的字符串

c++ - 这个 Windows API 调用 WaitForSingleObject 有什么问题?

C++ getline 使用逗号作为分隔符的多个变量类型

c++ - 使用线程的矩阵乘法

c++ - 控制台窗口无输出 :codeblocks