【发布时间】:2020-11-07 00:58:04
【问题描述】:
我正在学习 C++,遇到了一个可以用我以前的编程经验(主要是 C 和 Java;一些但有限的 OOP 经验)解决的问题,但我想知道什么才是合适的、现代的C++ 解决方案。问题涉及具有不同返回类型的虚函数的继承和派生类版本。基于多个 Stack Overflow 线程,这样的事情是不可能的。那么接下来我该怎么做呢?
为了练习 C++ 功能,我正在编写一个光线追踪器。我有一个虚拟基类Object 和派生类Polyhedron 和Polygon 来描述光可以与之交互的对象Rays。 (实际上,我有中间虚拟类 Solid 和 Face, 以及派生类 Sphere、Cylinder、Circle 以及 Polyhedron 和 Polygon,但为了简单起见,让我们在这里忘记它们。)目前,我只实现了光的发射和吸收,即Ray 只在没有任何折射或反射的情况下直行。 Polyhedron 内的吸收与强度(指数衰减)成正比,因此我必须找出 Ray 穿过的物体,并将 Ray 的强度从其源向前整合到它撞击探测器的位置。我有一个向量std::vector<std::shared_ptr<Intersection>> intersections 来存储Ray 与模拟场景中的对象的所有这些交集。一个交叉点需要包含交叉点Points、交叉点Polygon 面和Polyhedron 本身用于Polyhedron 对象,或者交叉点Point 和Polygon 面本身用于Polygon目的。因此,我希望派生类Intersection_Polyhedron 和Intersection_Polygon 来覆盖对Intersection::modulate_intensity(const double intensity_before) const 的调用,这应该在传递相关对象后返回Ray 的强度。换句话说,我想避免检查相交对象的类型,而是在计算对Ray 强度的调制时利用继承。
我想让每个Ray 简单地循环一个向量std::vector<std::shared_ptr<Object>> objects,其中包含模拟场景中的所有对象,调用虚函数Object::get_intersection(const Ray& ray) const 并得到Intersection_Polyhedron 或Intersection_Polygon 作为回报交叉点的类型(如果它带有 Polyhedron 或 Polygon)。指向这些派生交集对象的指针将被推回intersections,intersections 将根据与Ray 原点的距离进行排序,然后循环调用并覆盖Intersection::modulate_intensity() 以确定Ray的探测器上的最终强度。对我来说,这听起来像是实现此目的的 C++/OOP 方式,但似乎不可能,因为派生类的基类虚函数版本必须都具有相同的返回类型。那我该怎么做呢?
(目前,我从get_intersection() 为Polyhedrons 和Polygons 返回一个单一类型的Intersection。作为其成员,Intersection 具有相交Points 和相交std::shared_ptr<Polygon> 面的向量和std::shared_ptr<Polyhedron>(这是nullptr 用于Polygons,因为没有大容量)。为了区分Polyhedrons 和Polygons 的交叉点,我简单地检查是否有一个或两个交叉点Points . 这不是太不优雅,但现代 C++ 必须提供更好的方法来实现这一点,对吧?)
一些非常类似于 C++ 的伪代码来进一步阐明我想要实现的目标:
// ...
// create objects in a scene
std::vector<std::shared_ptr<Object>> objects;
// ...
// find a ray's intersections with the objects
std::vector<std::shared_ptr<Intersection>> intersections;
for(const auto& object : objects) {
// virtual class Object's function overridden with that of Polyhedron or Polygon
// returns std::shared_ptr<Intersection_Polyhedron> or std::shared_ptr<Intersection_Polygon> based on type of object
auto intersection = object->get_intersection(ray);
intersections.push_back(intersection);
}
// sort the intersections with std::sort and a lambda expression
// ...
// calculate a ray's intensity
double intensity = 0.0;
for(const auto& intersection : intersections) {
// virtual class Intersection's function overridden with that of Intensity_Polyhedron or Intensity_Polygon
intensity = intersection->modulate_intensity(intensity);
}
// ...
【问题讨论】:
-
由于
Intersection是Intersection_Polyhedron和Intersection_Polygon的基类,object->get_intersection(ray)都可以为虚方法返回std::shared_ptr<Intersection>... -
您是否暗示
Polyhedron::get_intersection()会构造一个Intersection_Polyhedron但会返回一个std::shared_ptr<Intersection>,而Polygon::get_intersection()会构造一个Intersection_Polygon但也会返回一个std::shared_ptr<Intersection>给它?然后当intersection->modulate_intensity()被调用时,它会被Intersection_Polyhedron::modulate_intensity()或Intersection_Polygon::modulate_intensity()覆盖。我想知道为什么我没有想到这一点。我猜这些新的继承和智能指针的东西已经融化了我的大脑......
标签: c++ inheritance overriding