1.子类转换为父类

子类转换为父类之后,不能调用子类独有的函数和成员变量,只能调用子类继承的虚函数,利用

多态的特性。

#include <iostream>

class base {
public:
    virtual void Show()
    {
        std::cout << "base class" << std::endl;
    }
    int a = 1;
};

class Drived :public base
{
public:
    void Show()
    {
        std::cout << "A class" << std::endl;
    }

    void ShowA()
    {
        std::cout << "ShowA fun" << std::endl;
    }

    int b = 2;
    int c = 3;
};

int main()
{
    Drived* drive_class = new Drived();
    base* base_class = (base*)drive_class;
    base_class->Show(); //可以调用子类重写父类的虚函数
    //base_class->ShowA(); //不能调用子类的独有函数,会报错
    printf("%d\n", base_class->a); //可以调用父类独有的成员变量
    //printf("%d\n", B->b); //调用子类独有的成员变量会报错
    //printf("%d\n", B->c);
   
}

转换为父类指针之后,不能调用ShowA()函数,和子类的b,c成员变量。

只能调用Show()函数,和成员变量a

输出结果

c++父类转换为子类,子类转换为父类,子类父类指针相互强制转换-LMLPHP

2.父类转换为子类

父类转换为子类是会出现异常,因为子类比父类有更多的成员变量和函数。如果访问子类自己独有的成员变量,会访问到未知的地方。

2.1父类转换成子类,调用子类的成员变量。

#include <iostream>

class base {
public:
    virtual void Show()
    {
        std::cout << "base class" << std::endl;
    }
    int a = 1;
};

class Drived :public base
{
public:
    void Show()
    {
        std::cout << "A class" << std::endl;
    }

    void ShowA()
    {
        std::cout << "ShowA fun" << std::endl;
    }

    int b = 2;
    int c = 3;
};

int main()
{
    base* Base = new base();
 
    Drived* drive_class = (Drived*)Base;

    int m = drive_class->b; //这里b的值初始值是2,但是m的值却不是2.因为drive_class->b指向了未知的地方

    printf("%d", m);
   
}

c++父类转换为子类,子类转换为父类,子类父类指针相互强制转换-LMLPHP

这里b的值初始值是2,但是m的值却不是2.因为drive_class->b指向了未知的地方

2.2父类转换成子类,调用子类的成员函数。

#include <iostream>

class base {
public:
    virtual void Show()
    {
        std::cout << "base class" << std::endl;
    }
    int a = 1;
};

class Drived :public base
{
public:
    void Show()
    {
        std::cout << "A class" << std::endl;
    }

    void ShowA()
    {
        std::cout << "ShowA fun" << std::endl;
    }

    int b = 2;
    int c = 3;
};

int main()
{
    base* Base = new base();
 
    Drived* drive_class = (Drived*)Base;

    drive_class->Show();
    drive_class->ShowA();
   
}

输出结果

c++父类转换为子类,子类转换为父类,子类父类指针相互强制转换-LMLPHP

调用show()函数的时候调用的还是,父类的虚函数,原因是根本没有子类的实例化对象。

调用ShowA()函数的时候,能正常的调用,可能是因为,声明类Drived的时候,ShowA函数已经存在于 内存的全局代码段数据存储区了,成员函数和成员变量是不一样的。

Tips:所以上述这种父类转子类是不安全的转换,调用成员变量的时候,指向了未知的地方。

如果父类转子类的时候,实例化对象包含有子类的时候这种,转换才是安全的。

比如

#include <iostream>

class base {
public:
    virtual void Show()
    {
        std::cout << "base class" << std::endl;
    }
    int a = 1;
};

class Drived :public base
{
public:
    void Show()
    {
        std::cout << "A class" << std::endl;
    }

    void ShowA()
    {
        std::cout << "ShowA fun" << std::endl;
    }

    int b = 2;
    int c = 3;
};

int main()
{
    base* Base = new Drived();
 
    Drived* drive_class = (Drived*)Base;

    drive_class->Show();
    drive_class->ShowA();
    int m = drive_class->b;
    printf("%d", m);
   
}

输出结果

c++父类转换为子类,子类转换为父类,子类父类指针相互强制转换-LMLPHP

3.避免不安全的父类转换成子类

使用强制转换符dynamic_cast来避免不安全的强制转换

#include <iostream>

class base {
public:
    virtual void Show()
    {
        std::cout << "base class" << std::endl;
    }
    int a = 1;
};

class Drived :public base
{
public:
    void Show()
    {
        std::cout << "A class" << std::endl;
    }

    void ShowA()
    {
        std::cout << "ShowA fun" << std::endl;
    }

    int b = 2;
    int c = 3;
};

int main()
{
    base* Base = new Drived();
 
    Drived* drive_class = dynamic_cast<Drived*>(Base);
    if (drive_class != NULL)
    {
        printf("进入转换1");
        drive_class->Show();
        drive_class->ShowA();
        int m = drive_class->b;
        printf("%d", m);
        
    }

    Base = new base();
    drive_class = dynamic_cast<Drived*>(Base);
    
    if (drive_class != NULL)
    {
        printf("进入转换2");
        drive_class->Show();
        drive_class->ShowA();
        int m = drive_class->b;
        printf("%d", m);

    }
    
   
}

输出结果

c++父类转换为子类,子类转换为父类,子类父类指针相互强制转换-LMLPHP

02-07 15:46