想象一下,我有一个Base类,以及两个派生自它的类,一个和两个。在Java中,我可以有以下场景:
Base b;
if(condition)
b = new One();
else
b = new Two();
在运行时确定对象类型(上面的对象在堆上)。
在C ++中,我希望能够在运行时实例化对象类型 - 我所知道的是它们都共享相同的Base类型 - 但是我想保持它的堆栈分配,如下所示:
Base b;
最好的方法是什么?
答案 0 :(得分:1)
最好的方法是什么?
你不能。如果将变量类型声明为Base
,则它的堆栈分配将适合于保存Base
的实例,但不适用于派生类型的实例(可能更大,但即使它是不,你仍然无法做你所要求的; C ++中变量的运行时类型总是与其声明的类型相同)。最好的情况是,您可以将派生实例slice转换为Base
- 类型变量。
最好的办法是使用一个指针,可选地包含在shared_ptr
或unique_ptr
中,以提供类似的语义(即,当对象超出范围时,让对象自动销毁,假设所有权还没有被转移。
Base* b = (condition) ? (Base *) new One() : new Two();
auto bptr = shared_ptr<Base>(b);
请注意,这给你的实际上与Java相同。对象本身是堆分配的,但对它的引用是堆栈分配的。尽管有语法,但引用类型的Java变量本质上等同于C ++中的指针。
答案 1 :(得分:0)
举个例子:
Derived d;
Base* b = &d;
d
在堆栈上(自动内存),但多态仍然可以在b
上运行。
如果您没有基类指针或对派生类的引用,则多态性不起作用,因为您不再具有派生类。取
Base c = Derived();
由于切片,c
对象不是Derived
,而是Base
。因此,从技术上讲,多态性仍然有效,只是你不再需要Derived
个对象来讨论。
现在拿
Base* c = new Derived();
c
只是指向记忆中的某个地方,而你真的不在乎这是Base
还是Derived
,而是对virtual
方法将动态解决。
因此,似乎与Java不同,没有堆分配或指针方式就无法实现动态绑定。
答案 2 :(得分:0)
正如评论所说,你做不到。嗯,你可以,但那不会运行:
Base &b = *(condition ? (Base *)&One() : (Base *)&Two()); // BROKEN CODE DO NOT USE
(使用-fpermissive
构建,但不要这样做!)
自One
&amp; Two
个对象是临时对象。单步执行下一行=&gt; b
将无效不要这样做(不确定我已经说过了)
以下工作,但并不完美:在堆栈上构建两个对象,所以只有在你负担得起的情况下才行。只需根据条件选择:
One one;
Two two;
Base &b = *(condition ? (Base *)&one : (Base *)&two);
为了避免双重分配,我在使用方面最接近的事情是采用已分配对象的引用(仍然不是自动变量,抱歉):
Base &b = *(condition ? (Base *)new One() : (Base *)new Two());
因此,您可以在代码中使用b
作为Base
。
您仍然需要使用
删除内存delete (&b);
答案 3 :(得分:-1)
为了在C ++中使用继承,您需要定义一个指针,而不是静态对象,然后使用<div class="container">
<div class="row">
<div class="col-md-4 col-sm-4">
<div class="row">
<div class="col-md-12 border">
1
</div>
<div class="col-md-12 border">
2
</div>
</div>
</div>
<div class="col-md-4 col-sm-4">
<div class="row">
<div class="col-md-12 border long">
3
</div>
</div>
</div>
<div class="col-md-4 col-sm-4">
<div class="row">
<div class="col-md-12 border">
4
</div>
<div class="col-md-12 border">
5
</div>
</div>
</div>
</div>
</div>
关键字对其进行实例化。
示例:
new