堆栈上的多态对象?

Cap*_*ffe 30 c++ polymorphism

之前的一个问题中, 我引用了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也犯了"堆分配"的错误,这在技术上是不准确的.

(注意:这并不意味着通用基类是"好"的!)

  • @John:垃圾.这是通过`VBase&`的调用.[这是一个显示你的断言错误的例子.](http://codepad.org/kKdD1qm9)[编辑:lol,ok] (2认同)

Fel*_*bek 6

我认为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-一个关系,即继承类对象具有与它们的基类.