创建基类对象的向量并在其中存储派生类对象

2024-03-27

我正在尝试创建一个员工数据库(员工向量)。有 3 种类型的员工,即。 Employees 是基类,Manager、Engg 和 Scientist 是派生类。 每个员工都有名字和姓氏。除了名字之外,这 3 种类型的员工中的每一种都有独特的统计数据,即。经理每周有多少次会议,而工程师则有工作经验等等。

我有一些问题 1. 我应该将派生对象向上转换为基类还是将基类向下转换为派生类? 2.如何使用多态性来重写方法,因为我希望用户添加员工类型,并根据所选类型显示相应的输入字段,即。如果是经理,除了名字和姓氏之外,该计划还应该询问每周举行的会议?

这是我的班级文件

class Employee{
public:
Employee();
 Employee(string fName, string lName, int sal);
virtual void printEmp();
string getFirstName();
string getLastName();

protected:
string m_fName;
string m_lName;
int m_sal;
};


class Manager : public Employee{
public:
Manager();
Manager(string fName, string lName, int sal, int meets, int hols);
void printEmp();


protected:
int m_meets;
int m_hols;
};

这是实现

Employee::Employee(){
m_fName = "Default";
m_lName = "Default";
m_sal = 0;
}


Employee::Employee(string fName, string lName, int sal){
m_fName = fName;
m_lName = lName;
m_sal = sal;
}

void Employee::printEmp(){
cout << "First Name: " << m_fName << endl
    << "Last Name: " << m_lName << endl
    << "Salary: " << m_sal << endl;
}


string Employee::getLastName(){
return m_lName;
}

string Employee::getFirstName(){
return m_fName;
}

Manager::Manager(string fName, string lName, int sal, int meets, int hols) :         Employee(fName, lName, sal), m_meets(meets), m_hols(hols)
{
//empty
}

void Manager::printEmp(){
Employee::printEmp();
cout << "Meets/Week: " << m_meets << endl
    << "Holidays/Year: " << m_hols << endl << endl;

这是主要的

int main(){

    bool exit = false;
    vector<Employee*> dBVector;

    while (!exit){

        cout << "Welcome to Employee Database, Enter an option to continue..." << endl;
        cout << "1) Add an Employee, 2) Delete an Employee, 3) Save Database, 4) Exit" << endl;
        int input;
        cin >> input;

        string fNameInp;
        string lNameInp;
        int salInp;
        string lNameSearch;
        int i; // for loop in Delete employee case
        bool deleted = false;

        switch (input){
        case 1: //Add
            cout << "1) Add a Manager, 2) Add an Engg, 3) Add a Researcher" << endl;
            int empInput;
            cin >> empInput;



            if (empInput == 1){


                cout << "Enter First Name: ";
                cin >> fNameInp;

                cout << "Enter Last Name: ";
                cin >> lNameInp;

                cout << "Enter Salary: ";
                cin >> salInp;

                cout << "Number of meetings/week: ";
                int meetsInp;
                cin >> meetsInp;

                cout << "Number of holidays/year: ";
                int holsInp;
                cin >> holsInp;

                Manager mEmp(fNameInp, lNameInp, salInp, meetsInp, holsInp);
                Employee &emp = mEmp;
                dBVector.push_back(&mEmp);
                dBVector[dBVector.size()-1]->printEmp();

            }

            else if (empInput == 2){
                cout << "Enter First Name: ";
                cin >> fNameInp;

                cout << "Enter Last Name: ";
                cin >> lNameInp;

                cout << "Enter Salary: ";
                cin >> salInp;

                cout << "Cpp Experience (Y/N): ";
                string cppInp;
                cin >> cppInp;

                cout << "Years of experience: ";
                float expInp;
                cin >> expInp;

                cout << "Engg Type (Chem, Mech, IT): ";
                string typInp;
                cin >> typInp;

                Engg eEmp(fNameInp, lNameInp, salInp, cppInp, expInp, typInp);
                Employee &emp = eEmp;
                dBVector.push_back(&eEmp);
                dBVector[dBVector.size() - 1]->printEmp();

            }

            else if (empInput == 3){
                cout << "Enter First Name: ";
                cin >> fNameInp;

                cout << "Enter Last Name: ";
                cin >> lNameInp;

                cout << "Enter Salary: ";
                cin >> salInp;

                cout << "School of PhD: ";
                string schoolInp;
                cin >> schoolInp;

                cout << "Topic of PhD: ";
                string topImp;
                cin >> topImp;

                Researcher rEmp(fNameInp, lNameInp, salInp, schoolInp, topImp);
                Employee &emp = rEmp;
                dBVector.push_back(&rEmp);
                dBVector[dBVector.size() - 1]->printEmp();

            }
            break;

        case 2: // Delete Emp
            for (int x = 0; x < dBVector.size(); x++){
                dBVector[x]->getLastName();
                cout << endl;
            }

            cout << "Input Last name of the employee to delete: " << endl;
            cin >> lNameSearch;
            for (i = 0; i < dBVector.size(); i++){
                if (dBVector[i]->getLastName() == lNameSearch){
                    dBVector.erase(dBVector.begin() + i);
                    cout << dBVector[i]->getFirstName() << "has been deleted from database";
                    deleted = true;
                    break;
                }
            }
            if (deleted == false && i == dBVector.size()){
                cout << "No Employee with Last Name - " << lNameSearch << " exists in Database." << endl;
            }
            else
                break;

        case 3: //save
            cout << "saving..." << endl;
            break;

        case 4: //exit
            exit = true;
            break;
        }
    }
}
Please Help!

首先,如果你想使用多态性,你需要在向量中存储指针。由于向量是员工的唯一所有者,例如std::vector<std::unique_ptr<Employee>>会合适的。

编辑:我看到您已经更新了向量以使用指针。但是您正在存储指向本地堆栈分配对象的指针,例如mEmp。这将不起作用,当mEmp变量在右大括号处超出范围,该对象将被删除,并且向量中将留下一个指向已删除对象的悬空指针。使用这个悬空指针是未定义的行为。您需要分配Manager在堆上使用new。这样,当变量超出范围时,该对象将不会被删除,但您确实需要记住在完成后删除该对象。就像是unique_ptr让这变得容易。

关于您的问题:

  1. 尽量减少显式强制转换,尤其是向下强制转换。当您存储Employee在向量中,它将从派生类隐式向上转换为Employee但除此之外,没有太多铸造的必要。
  2. 当涉及到重写方法时,如果您调用虚拟方法,您大致上有正确的想法printEmp上的方法Employee它将调用派生类中的重写指针。

    如果您愿意将用户输入的责任归为Employee您可以简单地添加一个虚拟方法,使用用户的适当输入来初始化员工。但我很想将其与域对象分开。无论如何,您需要一个有关用户选择员工类型的 switch 语句,因此多态性不会给您带来太多好处。

    如果您确实想使用多态性来创建员工,我建议使用诸如抽象工厂模式之类的东西。

无论如何,这是我的建议:

#include <vector>
#include <string>
#include <iostream>
#include <memory>

class Employee {
 public:
  Employee(std::string fName, std::string lName, int sal);
  virtual ~Employee();

  virtual void printEmp();

 protected:
  std::string m_fName;
  std::string m_lName;
  int m_sal;
};

class Manager : public Employee {
 public:
  Manager(std::string fName, std::string lName, int sal, int meets, int hols);
  void printEmp() override;

 protected:
  int m_meets;
  int m_hols;
};

Employee::Employee(std::string fName, std::string lName, int sal)
  : m_fName(fName), m_lName(lName), m_sal(sal) {
}

Employee::~Employee() {
}

void Employee::printEmp(){
  std::cout << "First Name: " << m_fName << "\n"
            << "Last Name: " << m_lName << "\n"
            << "Salary: " << m_sal << "\n";
}

Manager::Manager(std::string fName, std::string lName, int sal, int meets, int hols) 
  : Employee(fName, lName, sal), m_meets(meets), m_hols(hols){
}

void Manager::printEmp(){
  Employee::printEmp();
  std::cout << "Meets/Week: " << m_meets << "\n"
            << "Holidays/Year: " << m_hols << "\n";
}

std::unique_ptr<Manager> createManager() {
  std::cout << "Enter First Name: ";
  std::string fNameInp;
  std::cin >> fNameInp;

  std::cout << "Enter Last Name: ";
  std::string lNameInp;
  std::cin >> lNameInp;

  std::cout << "Enter Salary: ";
  int salInp;
  std::cin >> salInp;

  std::cout << "Number of meetings/week: ";
  int meetsInp;
  std::cin >> meetsInp;

  std::cout << "Number of holidays/year: ";
  int holsInp;
  std::cin >> holsInp;
  std::cout << "\n";

  return std::make_unique<Manager>(fNameInp, lNameInp, salInp, meetsInp, holsInp);
}

std::unique_ptr<Employee> createEmployee() {
  int input;  
  std::cout << "1) Add a Manager, 2) Add an Engg, 3) Add a Researcher\n";
  std::cin >> input;    
  switch (input){
    case 1:
      return createManager();   
    default:
      return nullptr;
  }
}

int main() {
  std::vector<std::unique_ptr<Employee>> dBVector; 

  std::cout << "Welcome to Employee Database, Enter an option to continue...\n";
  std::cout << "1) Add an Employee"
            << ", 2) Delete an Employee"
            << ", 3) Save Database"
            << ", 4) Exit\n";
  int input;
  std::cin >> input;

  switch (input){
    case 1:
      dBVector.push_back(createEmployee());
      break;
    default:
      break; // Do nothing
  }

  dBVector.at(0)->printEmp();    
}

Live demo http://melpon.org/wandbox/permlink/TFNPDTt6Eqiht0vK

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建基类对象的向量并在其中存储派生类对象 的相关文章

  • 如何使用 MVVM 更新 WPF 中编辑的数据? [复制]

    这个问题在这里已经有答案了 我正在为聊天应用程序构建 UI 设计 在尝试更新所选联系人的消息时遇到问题 选择现有联系人 选择编辑选项 然后编辑其属性 例如用户名和图像 后 唯一进行的更改是联系人的用户名和图像 我仍然想更改 MessageM
  • 键盘加速器在 UWP 应用中停止工作

    我正在尝试将键盘加速器添加到 UWP 应用程序中的 CommandBar 菜单项 当应用程序启动时 这工作正常 但在我第一次打开溢出菜单后 加速器停止工作 这似乎不会发生在主要命令 菜单之外 上 只有溢出菜单内的辅助命令才会发生 此外 单击
  • 使用API​​隐藏程序标题栏

    它可以使用 c 和 windows api 删除窗口控制台标题栏 如果是的话如何 请 这个简单的应用程序隐藏并显示其所在控制台的标题栏 它会立即将控制台标题更改为 guid 以查找窗口句柄 然后 它使用 ToggleTitleBar 使用找
  • C# 中四舍五入到偶数

    我没有看到 Math Round 的预期结果 return Math Round 99 96535789 2 MidpointRounding ToEven returning 99 97 据我了解 MidpointRounding ToE
  • 如何在不实例化一个类的情况下检查它是否继承了另一个类? [复制]

    这个问题在这里已经有答案了 假设我有一个如下所示的类 class Derived some inheritance stuff here 我想在我的代码中检查类似的内容 Derived is SomeType 但看起来像is运算符需要 De
  • 导出类时编译器错误

    我正在使用 Visual Studio 2013 但遇到了一个奇怪的问题 当我导出一个类时 它会抛出 尝试引用已删除的函数 错误 但是 当该类未导出时 它的行为会正确 让我举个例子 class Foo note the export cla
  • Qt 计算和比较密码哈希

    目前正在 Qt 中为测验程序构建面向 Web 的身份验证服务 据我了解 在数据库中存储用户密码时 必须对其进行隐藏 以防落入坏人之手 流行的方法似乎是添加的过程Salt https en wikipedia org wiki Salt cr
  • 矩阵向量变换

    我正在编写一个代码来制作软件蒙皮器 骨骼 皮肤动画 并且我正处于 优化 阶段 蒙皮器工作得很好 并且在 Core 上 1 09 毫秒内对 4900 个三角形网格与 22 个骨骼进行蒙皮Duo 2 Ghz 笔记本 我需要知道的是 1 有人可以
  • 方法“xxx”不能是事件的方法,因为该类派生的类已经定义了该方法

    我有一个代码 public class Layout UserControl protected void DisplayX DisplayClicked object sender DisplayEventArgs e CurrentDi
  • 是否有像 gccxml 这样的用于生成包装器的 C 标头解析器工具?

    我需要为一种新的编程语言编写一些 C 标头包装器 并且想要类似 gccxml 的东西 但不完全依赖 gcc 以及它在 Windows 系统上带来的问题 只需要读C而不是C 只要有完整的文档记录 任何格式的输出都可以 Linux Solari
  • C#中Enum中定义的value__是什么

    What value 可能在这里 value MSN ICQ YahooChat GoogleTalk 我运行的代码很简单 namespace EnumReflection enum Messengers MSN ICQ YahooChat
  • dropdownlist DataTextField 由属性组成?

    有没有一种方法可以通过 C 使 asp net 中的下拉列表的 datatextfield 属性由对象的多个属性组成 public class MyObject public int Id get set public string Nam
  • 正确使用“extern”关键字

    有一些来源 书籍 在线材料 解释了extern如下 extern int i declaration has extern int i 1 definition specified by the absence of extern 并且有支
  • 设计 Javascript 前端 <-> C++ 后端通信

    在我最近的将来 我将不得不制作一个具有 C 后端和 Web 前端的系统 要求 目前 我对此了解不多 我认为前端将触发数据传输 而不是后端 所以不需要类似 Comet 的东西 由于在该领域的经验可能很少 我非常感谢您对我所做的设计决策的评论
  • 不兼容的类型 - 是因为数组已经是指针吗?

    在下面的代码中 我创建一个基于书籍结构的对象 并让它保存多个 书籍 我设置的是一个数组 即定义 启动的对象 然而 每当我去测试我对指针的了解 实践有帮助 并尝试创建一个指向创建的对象的指针时 它都会给我错误 C Users Justin D
  • .NET JIT 编译的代码缓存在哪里?

    NET 程序首先被编译为 MSIL 代码 当它被执行时 JIT编译器会将其编译为本机机器代码 我想知道 这些JIT编译的机器代码存储在哪里 它只存储在进程的地址空间中吗 但由于程序的第二次启动比第一次快得多 我认为即使在执行完成后 该本机代
  • 使用 foreach 循环和 XmlNodeList C# 将新节点附加到节点列表

    目前我处理的是这样的XML类型 XML FILE http 20drive google com open id 0By5BxgNi9eGcRldxcEZNU0FDTzQ 参考XML文件 我想检查一个节点 如果找不到该节点 我必须将该节点附
  • C++ [Windows] 可执行文件所在文件夹的路径[重复]

    这个问题在这里已经有答案了 我需要访问一些文件fstream在我的 Windows 上的 C 应用程序中 这些文件都位于我的exe文件所在文件夹的子文件夹中 获取当前可执行文件的文件夹路径的最简单且更重要的 最安全的方法是什么 Use 获取
  • 使用 Chrome 和 Selenium 设置 LocalStorage

    我正在尝试使用 OpenQA Selenium 和 Chrome 设置本地存储键和值 我认为这相当微不足道 但我似乎无法让它发挥作用 我对 C 很陌生 所以我可能错过了一些东西 无论如何 我有这个功能 public static void
  • C# 粘贴到文本框时检查剪贴板中的字符

    有没有一些方法可以在粘贴到文本框 C 之前仅检查剪贴板中的字符 Ctrl V 和右键单击 gt 粘贴 但不使用 MaskedTextbox 在文本框文本更改中添加规则以仅接受数字 例如 private string value privat

随机推荐

  • 叉子和线程有什么区别?

    谁能解释一下叉子和线程之间的区别 分叉给你一个全新的进程 它是当前进程的副本 具有相同的代码段 当内存映像发生变化时 通常这是由于两个进程的不同行为 您会分离内存映像 写入时复制 但可执行代码保持不变 任务不会共享内存 除非它们使用某些内存
  • 配置 Xcode 4 工作区以在需要时构建依赖项的正确方法是什么?

    我的情况很简单 一个工作区有两个兄弟项目 一个主 iOS 应用程序和一个构建该应用程序使用的多个静态库目标的项目 以下是我配置构建的方式 将主应用程序的构建设置中的 用户标题搜索路径 指向库项目位置 通过源树 在我的应用程序的主要目标的编辑
  • 如何将json数组插入mysql数据库

    您好 我正在尝试将 json 数组插入到我的 MySQL 数据库中 我正在从我的 iPhone 传递数据 我已将数据转换为 json 格式 并且使用未插入到我的服务器中的 url 将数据传递到我的服务器 这是我的 json 数据 姓名 0
  • SKshapenode 没有响应Physicsbody

    我创建了一个SKShapeNode我已经分配了一个physicsBody到它 然而 当有接触时它不会被触发 的制作SKShapeNode code SKShapeNode gravityline SKSpriteNode lolo SKSp
  • 堆积条形图上的R ggplot标签[重复]

    这个问题在这里已经有答案了 我需要将数据放入堆栈条形图中 但是当我添加计数标签时 一些标签位于类别上方 一些标签位于类别下方 我尝试修改 geom text 函数的位置参数但无济于事 下面是一个可重现的示例 显示了该类别上方 下方 类别座位
  • 如何使用 Pipeline 引用 Jenkinsfile 目录?

    我有一个 groovy 文件 我想从 Jenkinsfile 运行 ie load script groovy 但是 如果该文件与 Jenkinsfile 存储在同一目录中 我不确定如何引用该文件 我正在从 git 加载 Jenkinsfi
  • 使用 stripplot 在 seaborn 中用中线绘制点

    我在seaborn中有以下情节 df pandas DataFrame sample X X X Y Y Y value 0 2 0 3 0 4 0 7 0 75 0 8 rep a b c a b c plt figure ax sns
  • 在 HQL 或 Criteria 中获取 DATEPART?

    如何使用 HQL 或 Criteria 获取时间的 DATEPART 我用谷歌搜索并得到了一些提示 但还不够 如果有人以前经历过 请告诉我们 提前致谢 看看这篇关于在nhibernate中使用sql函数 http ayende com Bl
  • mySQL 每日从一个表备份到另一个表

    如果我有两个具有相同定义的表 我将如何每天备份其中的数据 我可以使用 mySQL Administrator 执行类似的操作吗 每天中午 12 00 将 main table 中的所有行复制到 backup table 如果是增量备份会更好
  • Android 上的辅助功能测试自动化

    我最近开始研究 Android 上的自动化辅助功能测试 网络上没有太多信息 有人探索过这个或者目前正在这样做吗 如果是这样 您能分享您的想法 方法吗 似乎 Android 的 uiautomator 依赖于辅助功能来工作 但它不支持测试辅助
  • FullCalendar:事件最初未从函数调用(AJAX)渲染

    我已将 FullCalendar 配置为从 AJAX 请求中提取其事件 但首次加载页面时它们不会在日历上呈现 document ready function sh1client new Array sh2client new Array s
  • 为什么回调在 Ruby on Rails 中使用符号

    我很难理解何时以及何时不应该在 Rails 中使用符号 我知道符号与没有许多方法的字符串并没有太大不同 我还知道这些符号是很好的键 因为同名的符号在内存中占据一个地址 我很难理解为什么 Rails 决定在某些情况下使用符号 如果我有回调 b
  • 主机名未使用 Winsock 转换为 IP 地址

    getaddrinfo 不会将主机名转换为 IP 地址 因此不会connect 到服务器 我的实现有问题吗 编译时没有警告消息 这个函数调用的是connect正确的 connect client result gt ai addr resu
  • 在 Python 中编写仅附加 gzip 日志文件

    我正在构建一项服务 在其中记录来自多个源的纯文本格式日志 每个源一个文件 我不打算轮换这些日志 因为它们必须永远存在 为了使这些永远存在的文件更小 我希望我可以在飞行中对它们进行 gzip 压缩 由于它们是日志数据 因此文件压缩得很好 在
  • 当对象包含 ng-repetate 时,如何使用 angularFire 保存 Firebase 对象 $asArray()

    我最近从 angularfire 0 6 切换到 0 8 0 我在保存包含数组本身的列表项时遇到问题 我的对象account看起来像这样 JQruasomekeys0nrXxH created 2014 03 23T22 00 10 176
  • Python 与格式 '%Y-%m-%dT%H:%M:%S%Z.%f' 不匹配

    我尝试在Python中将字符串转换为日期时间对象 但我找不到我的格式有任何问题 Y m dT H M S Z f import datetime datetime datetime strptime 2019 11 19T17 22 23
  • 使用 getFilesDir() 时应用程序上下文返回 null

    我不知道为什么会发生这种情况 当我检查 DDMS 时也没有文件目录 我正在尝试在我的应用程序子类中访问此文件夹 知道为什么会发生这种情况吗 我需要应用程序上下文是全局的 这样我就可以在不扩展 Activity 的类上使用 package m
  • Selenium-Webdriver:找到元素后获取属性

    我对自动化的东西还很陌生 所以这听起来像是一个愚蠢的问题 在发布问题之前 我确实用谷歌搜索了它 不管怎样 问题就在这里 我正在 Android 设备上进行自动化测试 其中一项测试是验证某个项目是否已被标记为 收藏夹 页面代码片段为 li c
  • Android Studio 2.3 错误:无法加载类“com.google.common.collect.ImmutableSet”

    大家 突然 当我打开现有项目时 出现错误 错误 无法加载类 com google common collect ImmutableSet 导致此意外错误的可能原因包括 格拉德尔的 依赖项缓存可能已损坏 这有时会在网络连接后发生 连接超时 重
  • 创建基类对象的向量并在其中存储派生类对象

    我正在尝试创建一个员工数据库 员工向量 有 3 种类型的员工 即 Employees 是基类 Manager Engg 和 Scientist 是派生类 每个员工都有名字和姓氏 除了名字之外 这 3 种类型的员工中的每一种都有独特的统计数据