c++ - 当子元素位于父类向量中时,访问父类中的子成员
问题描述
我在父类向量中有多个子类,每个子类都有自己的类型。父母有一个虚getType
函数,每个孩子都用自己的虚函数覆盖它;甚至不确定我是否需要这个 TBH,但我从父类 C++ 中的这个 Access 子成员中获得
当我遍历向量时(此处未显示循环),类型只是父级的类型,因为它是父级的向量,但我需要使用其自己的构造函数创建的每个子级的类型。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Parent
{
private:
string type = "parent";
public:
virtual string getType()
{
return type;
}
};
class Child1 : public Parent
{
string type = "type1";
public:
string getType()
{
return type;
}
};
class Child2 : public Parent
{
string type = "type2";
public:
string getType()
{
return type;
}
};
//main.cpp
int main()
{
vector<Parent> children;
Child1 t1;
Child2 t2;
children.push_back(t1);
children.push_back(t2);
//THIS WORKS
cout << t1.getType(); // returns type1
// I NEED THIS TO WORK
cout << children[0].getType(); // returns parent.
cout << children[1].getType(); // I need type1 && type2
}
我怎样才能做到这一点?我无法知道每个孩子是什么类型的孩子,还是有其他方法可以做到这一点?
解决方案
您刚刚尝试了切片。
AChild
是Parent
加了一些东西。
当你尝试将 aChild
放入 的向量中时Parent
,只有其中Parent
每个Child
ren 的一部分放入向量中(因为向量中不包含Child
ren 而是包含Parent
s);因此得名slicing。
为了获得您正在寻找的动态多态性,您需要一个指向 ; 的指针向量。Parent
这样,每个指向的元素都可以是 aParent
或 aChild
并相应地表现。
这通常通过动态分配向量中的每个元素来完成,但这不是强制性的。例如,您可以将所有Parent
s 存储在一个向量中,将所有Child
ren 1 存储在另一个中,依此类推,最后使用指针向量以任意顺序指定其中一些。
如果您决定单独分配每个Parent
/ Child
,您应该考虑智能指针,std::unique_ptr<T>
而不是原始指针和new
/ delete
。
您将在下面发现您的示例稍作修改以获得动态多态性。std::unique_ptr<T>
由于/ ,它依赖于每个元素的动态分配std::make_unique()
。
请注意,由于动态多态性,您需要一个virtual
析构函数(即使它没有什么特别的作用)。由于这种类型的层次结构旨在用于动态多态性,因此鼓励通过禁止使用复制/移动操作来防止切片(您刚刚经历过)。因此,您必须提供一个或多个满足您需求的构造函数(但这很常见)。
我的最后一条建议是«避免动态多态性;更喜欢template
» 但这是另一个话题 ;^)
/**
g++ -std=c++17 -o prog_cpp prog_cpp.cpp \
-pedantic -Wall -Wextra -Wconversion -Wno-sign-conversion \
-g -O0 -UNDEBUG -fsanitize=address,undefined
**/
#include <iostream>
#include <string>
#include <vector>
#include <memory> // std::unique_ptr<T>, std::make_unique()
class Parent
{
public:
virtual ~Parent() =default; // ensure correct destruction
// forbid copy and move in order to prevent slicing
Parent(const Parent &) =delete;
Parent &operator=(const Parent &) =delete;
Parent(Parent &&) =delete;
Parent &operator=(Parent &&) =delete;
Parent() =default; // provide a suitable constructor
virtual
const std::string &
getType() const
{
return type;
}
private:
// inline static // is probably better
const std::string type{"parent"};
};
class Child1: public Parent
{
public:
const std::string &
getType() const override
{
return type;
}
private:
// inline static // is probably better
const std::string type{"type1"};
};
class Child2 : public Parent
{
public:
const std::string &
getType() const override
{
return type;
}
private:
// inline static // is probably better
const std::string type{"type2"};
};
int
main()
{
const auto p=Parent{};
std::cout << "p: " << p.getType() << '\n';
const auto c1=Child1{};
std::cout << "c1: " << c1.getType() << '\n';
const auto c2=Child2{};
std::cout << "c2: " << c2.getType() << '\n';
auto people=std::vector<std::unique_ptr<Parent>>{};
for(auto i=0; i<2; ++i)
{
people.emplace_back(std::make_unique<Parent>());
people.emplace_back(std::make_unique<Child1>());
people.emplace_back(std::make_unique<Child2>());
}
for(const auto &e: people)
{
std::cout << e->getType() << '\n';
}
return 0;
}
推荐阅读
- python - 在 ubuntu18.04 中导入错误 tensorflow-gpu
- sql - 整数表示的 MSSQL Case 返回字符串
- pyomo - 将 Pyomo 数据命令文件直接加载到 Python 数据结构中
- java - 将浏览器时区传递给后端 springboot 应用程序以根据浏览器时区生成带有日期的报告
- ios - 将字符串从颤振发送到 iOS
- django - 如何在 Django 中从用户那里获取多个查询
- c# - 在 Azure 服务器目录中创建 PDF 文件的问题
- python - Tensorflow 到 Keras:在 Keras 模型上导入图定义错误
- angular - 更新到 Angular 6.1 后的路由问题
- python - 谷歌表python脚本条件格式自定义公式