万恶之源:
hittable_list world = static_cast<hittable_list>(make_shared<bvh_node>(world, 0, 1));
本文只讨论手段是否能通过编译,是否应该这样做、有无必要这样做 不是讨论的重点
1、static_cast能够实现父类指针和子类指针相互转换
这是众所周知的吧,不知道的可以百度一下static_cast的用法
class A {};
class B : public A {};
void test01()
{
//这样转换是OK的 父类指针 转 子类指针
A* ptrA = new A();
B* ptrB = static_cast<B*>(ptrA);
}
void test02()
{
//这样转换也是OK的 子类指针强转为父类指针
B* ptrA = new B();
A* ptrB = static_cast<A*>(ptrA);
}
int main()
{
// test01();
test02();
cin.get();
return 0;
}
2、尝试把子类A的指针转到子类B (失败)
下面这串代码,hittable_list和bvh_node具有相同父类hittable
hittable_list world = static_cast<hittable_list>(make_shared<bvh_node>(world, 0, 1));
测试1:首先搞个空的基类,俩儿子也是空的
- test01():SonA* 转换成 SonB —— error
- test02():SonA* 转换成 SonB* —— error
- test03(): SonA* 转成 Base* 再转 SonB*
#include <iostream>
using namespace std;
class Base {};
class SonA : public Base {};
class SonB : public Base {};
void test01()
{
SonA* ptrA = new SonA();
SonB B;
B = static_cast<SonB>(ptrA);
}
void test02()
{
SonA* ptrA = new SonA();
SonB* ptrB = static_cast<SonB*>(ptrA);
}
void test03()
{
SonA* ptrA = new SonA();
Base* ptr = static_cast<Base*>(ptrA);
SonB* ptrB = static_cast<SonB*>(ptr);
}
int main()
{
//test01(); //错误 C2440 “static_cast”: 无法从“SonA *”转换为“SonB”
//test02(); //错误 C2440 “static_cast”: 无法从“SonA *”转换为“SonB *”
test03(); //可以
cin.get();
return 0;
}
3、把子类A的指针转到子类B (成功)
Key idea :隐式类型转换
c++中,隐式类型转换允许我们做出这样的操作
#include <string>
#include <iostream>
using namespace std;
class Base
{
public:
Base() {}
Base(string str) // 注意这个构造函数需要的你传入的是string类的对象
{
cout << str << endl;
}
};
int main()
{
const char* c = "hello";
Base base1(c); // 发生隐式转换:编译器认为const char* 可以转换成 string类型
cin.get();
return 0;
}
利用隐式转换的思想,我们可以这样操作
- 给B一个有参构造,形参接收一个为 Base* 指针变量
- 此时如果我们传入一个SonA* 类型的指针变量,则会发生隐式转换,
- B因为有这个构造函数,就可以构造出一个B类型对象
#include <iostream>
using namespace std;
class Base {};
class SonA : public Base {};
class SonB : public Base
{
public:
SonB(){}
SonB(Base* base){}
};
int main()
{
SonA* ptrA = new SonA();
SonB b = static_cast<SonB>(ptrA);
cin.get();
return 0;
}
可以看到,代码中,hittable_list类里,确实刚好有个构造函数,符合上述情况
hittable_list world = static_cast<hittable_list>(make_shared<bvh_node>(world, 0, 1));
写给自己看,这行代码执行后,不光是转换了,还把bvh树给压到objects中了