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
输出结果
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);
}
这里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();
}
输出结果
调用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);
}
输出结果
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);
}
}
输出结果