创建/管理异构容器(c++)
Creating/managing a heterogenous container(c++)
我在正确构建一个容器时遇到了问题,该容器存储不同类型的类样本,这些样本都是单个抽象类的继承者。寄存器(容器(存储一个指向这些样本数组的指针,该指针具有抽象类的类型。每当我试图访问样本中包含的数据时,我只能成功检索基类中也能找到的部分。例如,过载<lt;在包含所有三个继承者的元素的寄存器上使用,将只在屏幕上写入抽象类部分,并忽略任何不存在的内容。现在我真的不知道问题是打印出正确存储的元素,还是存储已经以不合适的形式完成,所以这将是我的问题:应该如何正确地完成?这是代码:
class Register{
private:
int elementNum;
type * pData;
friend std::ostream &operator<<(std::ostream & os,const Register &v);
};
class type{
int a;
int b;
};
class type2: public type{
int c;
int d;
};
其他两个继承者的行为方式与type2相同。以下是主要部分:
int main ()
{
type2 A1(1,2,3,4);
type3 D1(4,5,6,7,8);
type4 H1(9,10,11,12,13);
std::cout<<A1<<D1<<H1<<endl;
Register R1;
R1.Add(0,A1);
R1.Add(1,D1);
R1.Add(2,H1);
R1.Display();
R1.MaxLength();
std::cout<<R1;
return 0;
}
运算符<lt;在寄存器上:
std::ostream &operator<<(std::ostream & os,const Register &v){
for(int i=0;i<v.elementNum;i++)
{
os<<v.pData[i]<<endl;
}
return os;
}
仅使用<lt;寄存器中的运算符或函数以这个问题结束。编辑:添加功能的实现:
void Register::Add(int position,type& T){
if(position<0||position>elementNum+1)
return;
type *pTemp = new type[elementNum+1];
if(elementNum==0)
{
pTemp[0]=T;
delete[]pData;
pData=pTemp;
}
else
{
for(int i=0,j=0;j<elementNum+1;i++,j++)
{
if(position!=j)
pTemp[j]=pData[i];
else
{
i--;
pTemp[j]=a;
}
}
delete[]pData;
pData=pTemp;
}
elementNum++;
}
您只能访问基类公共的公共成员,或者从基类中可用的虚拟方法
此外,您只能通过指针/引用访问虚拟方法,并且通常不能像使用pData
那样连续存储不同的类实例
如果您创建了一个virtual std::ostream &type::dump(std::ostream &os)
成员方法,并且override在type2
中,等等,那么您可以使每个overridenin方法显示其子类型特定的内容。
struct type {
virtual ostream &dump(ostream &os) {
os << a << " " << b << " ";
return os;
}
int a;
int b;
};
struct type2 : type {
// Can use parent implementation AND use subtype-specific members:
ostream &dump(ostream &os) override {
type::dump(os);
os << c << " " << d << " ";
return os;
}
int c;
int d;
};
// This class needs new "void Add(int pos, type &)" logic.
struct Register {
int elementNum;
type *pData; // next hint: this is almost definitely not what you want.
type **pda; // probably better (need to use new/delete to make types)
};
ostream &operator<<(ostream &os, Register const &v) {
for (int i = 0; i < v.elementNum; ++i) {
// Calls proper virtual method for each instance.
v.pData[i].dump(os); // XXX probably broken too
v.pda[i]->dump(os); // should look more like this
os << endl;
}
}
type *pTemp = new type[elementNum+1];
这将分配一个类型为type
的对象数组。对象永远不能更改其类型,也不能替换数组的元素,只能修改它。因此,Register
对象根本不包含任何派生类的对象,只包含基类类型的对象。
要想以困难的方式获得一个异构对象数组,您需要一个指针数组:
type **pTemp = new (type*[elementNum+1]);
要以正确的方式进行操作,您需要避开数组和原始指针,而是使用容器和智能指针:
class Register {
public:
const type& get(int pos) const;
type& get(int pos);
void Add(int pos, const type& obj);
void Add(int pos, std::unique_ptr<type>&& ptr);
// ...
private:
std::vector<std::unique_ptr<type>> m_data;
};
但不管怎样,你从函数Add
中放入了什么指针?
void Register::Add(int position,type& T);
可能不是传递的引用的地址&T
。谁知道那个对象什么时候会被销毁。new type(T)
也不好——它只是创建了一个基本类型的对象,忽略了T
的实际类型。因此,您可能需要一个clone()
方法,有时称为"虚拟副本构造函数":
class type {
public:
using pointer = std::unique_ptr<type>;
virtual ~type();
virtual pointer clone() const;
};
type::pointer type::clone() const {
return pointer(new type(*this));
}
type::pointer type2::clone() const {
return pointer(new type2(*this));
}
上面我放入了Add()
的两个过载。对象传递版本如下:
void Register::Add(int pos, const type& obj) {
if (pos<0)
return;
if (pos >= m_data.size())
m_data.resize(pos+1);
m_data[pos] = obj.clone();
}
如果您碰巧已经有了type::pointer
,而不仅仅是一个对象,那么另一个版本可能会很有用。有了这个重载,您就可以将它移动到Register
中,而不需要clone()
任何东西。
void Register::Add(int pos, type::pointer&& ptr) {
if (pos<0)
return;
if (pos >= m_data.size())
m_data.resize(pos+1);
m_data[pos] = std::move(ptr);
}
- 当vector是tje全局变量时,c++中vector的内存管理
- 如何维护资源管理器项目视图中当前可见的项目列表
- 如何在GTK程序运行时禁用屏幕保护程序/电源管理/屏幕消隐
- 资源管理设计模式
- 使用"Task"函数指针队列定义作业管理器
- 实现动态插件管理器
- Alt+Enter 在 Win32 应用中,管理大小调整和分辨率
- libcurl 和 DNS ttl 中的内部连接管理
- 当分配一个字符串值并稍后通过分配另一个值进行更改时C++如何管理内存?
- 在C++管理一家中国.txt
- 编译器资源管理器和 GCC 具有不同的输出
- 我们可以通过 IPC 传递具有动态管理成员的类对象吗?
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- Q没有管理权限的 exe 无法启动维护工具
- QT:管理来自 QNetworkReply 的回复
- 使用 std::vector<double> 访问由 std::unique_ptr<double[2] 管理的数据>
- 读取 TCP 标头并使用RAW_SOCKET管理 TCP 连接
- Windows 资源管理器中的图标在使用 resource.rc 时显示 2 个不同的图标
- 管理字符串文本的最佳做法
- 在 QNX 中,如何管理服务器和客户端之间的 IPC 连接?