在之前的一个问题中, 我引用了Stroustrup,了解为什么所有类的公共Object类在c ++中都存在问题.在该引文中有声明:
使用通用基类意味着成本:对象必须被堆分配为多态的;
我真的没有看过两次,因为它在Bjarnes的主页上,我想很多眼睛都会扫描那句话并报告任何错误陈述.
然而,一位评论者指出,情况可能并非如此,回想起来,我找不到任何理由这样做的理由.一个简短的测试用例产生了"VDerived :: f()"的预期结果.
struct VBase
{
virtual void f() { cout<<"VBase::f()"<<endl; }
};
struct VDerived:VBase
{
void f() { cout<<"VDerived::f()"<<endl; }
};
void test(VBase& obj){
obj.f();
}
int main(int argc, char** argv) {
VDerived obj;
test(obj);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当然,如果测试的形式参数test(VBase obj)是完全不同的,但这不是堆栈与堆参数,而是复制语义.
Bjarne是错误还是我错过了什么?
Lig*_*ica 12
对我来说看起来像多态.
当你有间接时,C++中的多态性就可以工作; 也就是说,a pointer-to-T或a reference-to-T.其中T存储的是完全不相干的.
Bjarne也犯了"堆分配"的错误,这在技术上是不准确的.
(注意:这并不意味着通用基类是"好"的!)
我认为Bjarne意味着obj,或者更准确地说它指向的对象,在这段代码中不能轻易地基于堆栈:
int f(int arg)
{
std::unique_ptr<Base> obj;
switch (arg)
{
case 1: obj = std::make_unique<Derived1 >(); break;
case 2: obj = std::make_unique<Derived2 >(); break;
default: obj = std::make_unique<DerivedDefault>(); break;
}
return obj->GetValue();
}
Run Code Online (Sandbox Code Playgroud)
您不能在堆栈上有一个更改其类的对象,或者最初不确定它属于哪个类.
(当然,要真正迂腐,人们可以通过使用一个位置,新的分配堆栈上的对象alloca-allocated空间.有复杂的解决方法在这里跑题了,但事实.)
以下代码也无法正常工作:
int f(int arg)
{
Base obj = DerivedFactory(arg); // copy (return by value)
return obj.GetValue();
}
Run Code Online (Sandbox Code Playgroud)
此代码包含一个对象切片错误:堆栈空间obj仅与类的实例一样大Base; 当DerivedFactory返回具有一些附加成员的派生类的对象时,它们将不会被复制到obj其中呈现为obj无效且不可用的派生对象(并且很可能甚至不能用作基础对象.)
总而言之,有一类多态行为无法以任何直接的方式使用堆栈对象实现.
当然,任何完全构造的派生对象,无论它存储在何处,都可以充当基础对象,因此可以多态地行动.这简单地从如下IS-一个关系,即继承类对象具有与它们的基类.
| 归档时间: |
|
| 查看次数: |
6701 次 |
| 最近记录: |