- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我实际上没有遇到“问题”,因为我的代码确实有效。我只是好奇我的实现是否合理且没有风险。
我一直在使用 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();
}
// ...
}
}
将不同类的对象存储在新
数组中是否存在任何风险,因为它们都具有相同的大小并且可以使用虚拟析构函数进行销毁?
我一直听说应该避免使用 new[]
。我确实找到了一些方法,可以使用带有类型标记的 union
的 vector
实现我想要的效果,但对我来说这似乎有点脏。有没有办法在将数据存储在 std::vector
中时实现多态性?
仅仅为了利用虚函数的便利而使用多态性的做法被认为是一种坏习惯吗?这么说我的意思是如果每个对象占用的内存对于每个派生类来说已经相同,那么它们可能会合并到一个存储自己类型的类中,并且每个成员函数只能根据自己的类型运行。我选择不这样做,因为在每个成员函数中都有巨大的 switch
结构对我来说也很脏。
在这种情况下选择连续内存好吗?有什么理由表明这种选择可能有害吗?
编辑:
事实证明我犯了很多错误,例如一次问太多问题。我想我会首先关注多态性和 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.
再次感谢所有的反馈和建议。
最佳答案
- 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];
_nodeList
是 DefaultNote
的数组没有别的!试图在其中存储一些东西 _nodeList[i] = ...
将永远改变存储对象的任何性质(注意 _nodeList[i] = Derived1;
不是 C++)。如果你想要多态性,你需要通过指针或引用来保留对象。那么第一个解决方案是正确的:std::vector<Base*> _nodeList;
.
- 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
的任何对象的地址或任何子类型。
- 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 重载...
- 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/
我在 Mac OsX 10.11 上使用 Xcode 7.0.1 (7A1001) 我使用 carthage 0.9.2 通过以下购物车文件下载reactivecocoa github“Reactiv
我正在将一个对象从属性“模型”(我从 Laravel 中的 Blade 属性模型中获得)分配给数据属性模型。后来数据属性模型发生变化,因为它绑定(bind)到表单输入字段。但 Prop “模型”也发生
当我更新数组内对象的属性然后作为组件的 Prop 传递时,在 svelte 中触发 react 性的正确方法是什么? let items = [{ id: 1, name: 'first'
我是 DRY principle 的坚定拥护者: Every piece of knowledge must have a single, unambiguous, authoritative rep
我正在实现一个需要以下功能的线程: 及时响应终止请求 推送消息 在等待消息时保持对 SendMessage 请求的响应 我对消息泵的初始实现使用了 GetMessage,如下所示: while not
在我的应用程序中,用户获得了一份已到达她的文档列表,并且可以对每个文档执行操作。 文件是分批提交的,当这种情况发生时,列表会增加。这一切都很好,这是预期的行为,但最好有一个按钮“暂停实时数据”,它会忽
我有一个属性为 的数据对象 displaySubtotal 我可以通过以下方式更新该属性的值: data.displaySubtotal = numPad.valueAsAString(); 我的方法
我需要一个垂直 slider 输入。由于内置的 sliderInput 函数无法做到这一点,因此我选择自己实现。根据this thread可以 (I) 使用 CSS 旋转 sliderInput
我正在从自定义用户权限管理系统迁移到 Alanning:roles v2.0 .我有一个非常基本的结构: 基本用户 用户组,每个用户组都有特定的设置。我将它们存储在一个“组”集合中。 管理群组的用户的
Shiny 中的响应式(Reactive)表达式将更改传播到需要去的地方。我们可以使用 isolate 来抑制一些这种行为。 ,但是我们可以抑制基于我们自己的逻辑表达式传播的更改吗? 我给出的例子是一
是否有(或可能有) react 性 Parsec (或任何其他纯函数式解析器)在 Haskell 中? 简而言之,我想逐个字符地为解析器提供数据,并获得与我提供的足够多的结果一样多的结果。 或者更简单
HTML(JADE) p#result Lorem ipsum is javascript j s lo 1 2 4 this meteor thismeteor. meteor input.sear
我有一个被导入函数更改的对象。 https://svelte.dev/repl/e934087af1dc4a25a1ee52cf3fd3bbea?version=3.12.1 我想知道如何使我的更改反
我有一个YUV 420半平面格式的图像,其中字节以这种方式存储: [Y1 Y2 ... [U1 V1.... Yk Yk+1...] Uk' Uk'+1] 其中Y平面的大小是UV平面的两倍,并
如何使用 ReactiveCocoa 订阅从 NSMutableDictionary 添加和删除的对象?另外,我想在它发生变化时广播通知。我的猜测是可以使用 RACMulticastConnectio
我正在构建一个带有多个选项卡的应用程序,其中一些选项卡涉及过多的计算,而另一些选项卡的计算速度很快。一个允许用户在 react 性或手动更新之间进行选择的复选框,与“刷新”按钮结合使用,将是理想的选择
我知道您可以在获取集合时使用 reactive: false 关闭 react 性。如何在内容可编辑区域内的集合字段中实现相同的效果?示例: Template.documentPage.events(
我想在 z3 中表示一个哈希函数,比如 SHA(x)。在做了一些研究之后,似乎 z3 不能很好地支持注入(inject)性,所以我不能有像这样的约束(虽然我意识到这并不是严格意义上的碰撞,但作为一种启
我正在解决一个问题,我想在仪表板中将数据显示为图表(通过 perak:c3 )和表格(通过 aslagle:reactive-table )。我的问题是数据是从 MongoDB 中的集合中提取的,它的
我的 ViewModel 中有这个函数,它返回一个信号,但内部 block 不起作用,我尝试添加断点,但它没有中断。这是我的代码。 func executeLoginAPI() -> RACSigna
我是一名优秀的程序员,十分优秀!