首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >static_pointer_cast<Derived> pReallyABase = static_pointer_cast<Derived>(pBase)成功了!为什么?

static_pointer_cast<Derived> pReallyABase = static_pointer_cast<Derived>(pBase)成功了!为什么?
EN

Stack Overflow用户
提问于 2014-07-31 03:47:28
回答 2查看 206关注 0票数 4

我不明白为什么这样行得通。pReallyABase是一个向下转换的shared_pointer< Derived >,它指向一个基类实例。

我理解为什么编译器允许我调用pReallyABase->onlyForDerived(),因为我将它定义为派生类指针,但是为什么当我尝试使用该指针调用派生类函数时,我不会得到运行时错误?

代码语言:javascript
复制
class Base { 
    public:
        virtual string whatAmI() {
            return "I am a Base";
        }
};

class Derived : public Base {
    public:
        virtual string whatAmI() {
            return "I am a Derived";
        }

        string onlyForDerived() {
            return "I can do Derived things";
        }
};


int main(int argc, char *argv[]) { 
    shared_ptr<Base> pBase = shared_ptr<Base>(new Base);
    shared_ptr<Derived> pReallyABase = static_pointer_cast<Derived>(pBase);

    cout << pReallyABase->whatAmI() << endl;
    cout << pReallyABase->onlyForDerived() << endl;  //Why does this work?
    return 0;
}

结果

代码语言:javascript
复制
I am a Base
I can do Derived things
EN

回答 2

Stack Overflow用户

发布于 2014-07-31 04:14:18

关于如何在C++中调用成员函数(非静态和非虚的),“C++对象模型内部”一书对此进行了解释:

一个C++设计标准是,非静态成员函数至少必须与其类似的非成员函数一样有效。选择成员函数实例不应该有额外的开销。这是通过在内部将成员实例转换为等效的非成员实例来实现的。在这些转换之后,它的每个调用也必须进行转换:例如:

代码语言:javascript
复制
obj.magnitude();

变成了

代码语言:javascript
复制
magnitude_7Point3dFv(&obj);

代码语言:javascript
复制
ptr->magnitude();

变成了

代码语言:javascript
复制
magnitude_7Point3dFv(ptr);

因此,如上面的示例所示,函数onlyForDerived没有使用派生类的任何成员变量,因此它是有效的。但这是一种未定义的行为,我们不应该依赖它。

票数 2
EN

Stack Overflow用户

发布于 2014-07-31 04:19:33

通过将Base对象视为Derived,您将自动获得未定义的行为,因此您看到的任何行为都是合法的。

在这种情况下,因为编译器“知道”派生指针的静态类型是Derived,所以它能够调用函数,即使这样做是不合法的。

它不会引发运行时错误,因为它不需要引发运行时错误(未定义就是未定义)。也就是说,如果函数是虚的,它可能会在大多数实现中崩溃,如果派生类具有派生函数引用的数据,则可能会崩溃或生成意外输出。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25045656

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档