gpt4 book ai didi

c++ - 通过连续内存实现多态性

转载 作者:行者123 更新时间:2023-11-28 04:02:42 25 4
gpt4 key购买 nike

我实际上没有遇到“问题”,因为我的代码确实有效。我只是好奇我的实现是否合理且没有风险。

我一直在使用 C++ 开发一个项目,在该项目中,我首先解析一个文件,然后相应地构建一个有向无环图结构。根据节点的类型,每个节点可能有 0~2 个外邻居。对于不同类型的节点,需要一些用于打印和访问的函数,我决定使用多态来实现。

我的第一个尝试是使用节点存储指向其外邻节点的指针来实现它。

class Base{
public:
Base(){}
virtual ~Base(){}
virtual foo()=0;
// ...
protected:
unsigned _index;
}

class Derived1: public Base{
public:
foo(){ /*Do something here...*/ }
private:
Base* _out1;
}

class Derived2: public Base{
public:
foo(){ /*Do something different here...*/ }
private:
Base* _out1;
Base* _out2;
}

int main(){
std::vector<Base*> _nodeList;
for(/*during parsing*/){
if(someCondition){
_nodeList.pushback(new Derived1);
}
// ...
}
}

由于节点的外邻节点在构建节点时可能尚未定义,因此我必须添加一些技巧来首先记住外邻节点的 id,并在完成所有节点的构建后连接它们。

但是,由于节点的数量是根据要解析的文件确定的,并且以后不会增长,所以我认为最好连续存储所有节点,并且每个节点存储其外邻节点的索引而不是指针。这让我可以跳过连接部分,也为其他部分带来了一些小好处。

我目前的版本如下:

// Something like this
class Base{
public:
Base(){}
virtual ~Base(){}
virtual foo()=0;
// ...
protected:
unsigned _index;
unsigned _out1;
unsigned _out2;
}

class Derived1: public Base{
public:
foo(){ /*Do something here...*/ }
}

class Derived2: public Base{
public:
foo(){ /*Do something a little bit different here...*/ }
}

int main(){
// EDITED!!
// Base* _nodeList = new DefaultNode[max_num];
Base* _nodeList = new Derived2[max_num];
for(/*during parsing*/){
if(someCondition){
// EDITED!!
// _nodeList[i] = Derived1;
new(_nodeList+i) Derived1();
}
// ...
}
}

我的问题

  1. 将不同类的对象存储在数组中是否存在任何风险,因为它们都具有相同的大小并且可以使用虚拟析构函数进行销毁?

  2. 我一直听说应该避免使用 new[]。我确实找到了一些方法,可以使用带有类型标记的 unionvector 实现我想要的效果,但对我来说这似乎有点脏。有没有办法在将数据存储在 std::vector 中时实现多态性?

  3. 仅仅为了利用虚函数的便利而使用多态性的做法被认为是一种坏习惯吗?这么说我的意思是如果每个对象占用的内存对于每个派生类来说已经相同,那么它们可能会合并到一个存储自己类型的类中,并且每个成员函数只能根据自己的类型运行。我选择不这样做,因为在每个成员函数中都有巨大的 switch 结构对我来说也很脏。

  4. 在这种情况下选择连续内存好吗?有什么理由表明这种选择可能有害吗?

编辑:

事实证明我犯了很多错误,例如一次问太多问题。我想我会首先关注多态性和 placement new 部分。下面是一个可测试的程序,我所说的“将不同派生类的对象存储在一个新的数组中,它在我的笔记本电脑上的行为如下所示。

#include <iostream>

class Base{
public:
Base(){}
virtual ~Base(){}
void virtual printType() =0;
};

class Derived1: public Base{
public:
Derived1(){}
void printType(){ std::cout << "Derived 1." << std::endl; }
};

class Derived2: public Base{
public:
Derived2(){}
void printType(){ std::cout << "Derived 2." << std::endl; }
};

int main(){
Base* p = new Derived1[5];
new(p+2) Derived2();
for(unsigned i = 0; i < 5; ++i){
(p+i)->printType();
}
}

结果:

Derived 1.
Derived 1.
Derived 2.
Derived 1.
Derived 1.

再次感谢所有的反馈和建议。

最佳答案

  1. Are there any risks to store objects of different class in an newed array, given that they are all of the same size and can be destructed using a virtual destructor?

这不是您的第二个命题中发生的情况:

Base* _nodeList = new DefaultNode[max_num];

_nodeListDefaultNote 的数组没有别的!试图在其中存储一些东西 _nodeList[i] = ...永远改变存储对象的任何性质(注意 _nodeList[i] = Derived1; 不是 C++)。如果你想要多态性,你需要通过指针或引用来保留对象。那么第一个解决方案是正确的:std::vector<Base*> _nodeList; .

  1. I've always heard that the use of new[] should be avoided. I did found some approaches that achieve what I want using vector of union with a type tag, but it seems somewhat dirty to me. Is there a way to achieve polymorphism while storing data in a std::vector?

应避免使用 new[] 是胡说八道。如前所述,如果您需要多态性,那么 std::vector<Base*> _nodeList;是完美的,因为这意味着您可以存储在 _nodeList 中类为 Base 的任何对象的地址或任何子类型。

  1. Is the practice of using polymorphism merely to make use of the convenience of virtual functions consider a bad habit? By saying so I mean if the memory taken by each object is already the same for each derived class, then they may be merged into one single class that store its own type, and each member function can just behave according to its own type. I chose not to do so since it also looks dirty to me to have huge switch structure in each member function.

子类型多态虚函数的使用。为什么是坏习惯?如果你不使用虚函数就意味着你在自己构造多态性,这可能是一件非常糟糕的事情。

现在,如果你的派生类就像你的例子中提出的那样,我可以建议你不要使用子类而只使用 ctor 重载...

  1. Is it good to choose contiguous memory in this case? Are there any reasons that such choice may be harmful?

我不确定是否真的理解为什么这对您来说是一个问题。 Contiguous memory 是没有害处的……这个问题至少没说清楚。

关于c++ - 通过连续内存实现多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59246965/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com