zoukankan      html  css  js  c++  java
  • 类的向上转型(安全)向下转型(不安全)

    类其实也是一种数据类型,也可以发生数据类型转换,不过这种转换只有在基类和派生类之间才有意义,并且只能将派生类赋值给基类,包括将派生类对象赋值给基类对象、将派生类指针赋值给基类指针、将派生类引用赋值给基类引用,这在 C++ 中称为向上转型(Upcasting)。相应地,将基类赋值给派生类称为向下转型(Downcasting)。
    向上转型非常安全,可以由编译器自动完成;
    向下转型有风险,需要程序员手动干预(有时编译器认为只是错误)
    赋值的本质是将现有的数据写入已分配好的内存中,对象的内存只包含了成员变量,所以对象之间的赋值是成员变量的赋值,成员函数不存在赋值问题。
    将派生类对象赋值给基类对象时,会舍弃派生类新增的成员,所以不存在安全问题。
    即使将派生类对象赋值给基类对象,基类对象也不会包含派生类的成员,所以依然不能通过基类对象来访问派生类的成员。
    这种转换关系是不可逆的,只能用派生类对象给基类对象赋值,而不能用基类对象给派生类对象赋值。理由很简单,基类不包含派生类的成员变量,无法对派生类的成员变量赋值。同理,同一基类的不同派生类对象之间也不能赋值。
    用派生类对基类的引用或者指针赋值决计不会发生截至的现象

    #include <iostream>
    #include <string>
    
    class Super
    {
    public:
        Super();
        Super(std::string &initialString);
        virtual ~Super();
    public:
        virtual void getString() const;
    
    private:
        std::string SuperString;
    };
    
    class Sub : public Super
    {
    public:
        Sub();
        Sub(std::string &initialString);
        virtual ~Sub();
    
    public:
        virtual void getString() const override ;
    
    private:
        std::string SubString;
    
    };
    
    Super::Super()
    :SuperString("")
    {
    
    }
    Super::Super(std::string &initialString)
    :SuperString(initialString)
    {
    
    }
    Super::~Super()
    {
    
    }
    void Super::getString() const
    {
        std::cout << SuperString << std::endl;
    }
    
    Sub::Sub()
    :SubString("")
    {
    
    }
    Sub::Sub(std::string &initialString)
    :SubString(initialString)
    {
    
    }
    Sub::~Sub() {}
    void Sub::getString() const
    {
        std::cout << SubString << std::endl;
    }
    int main()
    {
        std::string str1 = "Sub",str2 = "Super";
        std::string str3 = "Sub2",str4 = "Super2";
        Sub sub(str1);
        Super & super = sub;        //向上转型,派生类赋值给父类的引用或者父类的指针都是安全的
        super.getString();
    
        Super super1(str4);
        Sub *sub1 = static_cast<Sub*>(&super1);
        sub1->getString();
        return 0;
    }

    Sub
    S

    Super2

     然而就算是有时候用向下转换,也得用dynamic_cast<>的类型转换。这样做的好处就是:当指针dynamic_cast<>失败的话,将会指向nullptr,而不是其他的无意义的数据;当针对对象引用失败的时候就会抛出std::bad_cast异常

    Super *inSuper;
        Sub *sub1 = dynamic_cast<Sub*>(inSuper);
        if(sub1 != nullptr)
        {
            std::cout << "sub1 is not nullptr" << std::endl;
        } else
        {
            std::__throw_bad_cast();
        }

    程序会报错!!!

  • 相关阅读:
    把arguments转化成数组
    最小化重绘和重排
    选择器API
    事件委托
    WAhaha_hnu (zoj 2010 oct月赛)
    素数计数公式全面拉丁化改写小有改进Meissel公式梅塞尔Lehmer公式莱梅=勒梅尔筛法三种形式孟庆余公式(转载)
    NBUT 2013 Timed NOJ Training #005
    2013 腾讯马拉松初赛第一场
    hrboj 1683 树形DP
    哈尔滨2013校赛训练赛 4 解题思路
  • 原文地址:https://www.cnblogs.com/boost/p/10342125.html
Copyright © 2011-2022 走看看