问题描述
构建C ++程序时,出现错误消息。
对vtable的未定义引用
我有两个调用的虚拟抽象类,如果做错了什么,我就不太清楚自己在做错什么。 我从继承自抽象类的两个类中都遇到了错误。 我的抽象课是
未定义对“ vtable for hittable_list”的引用
对“ vtable for sphere”的未定义引用
hittable.h
#ifndef SPHERE_H
#define SPHERE_H
#include "hittable.h"
class sphere : public hittable
{
public:
sphere() {}
~sphere() {}
sphere(vecfloat cen,float r) : center(cen),radius(r) {}
bool hit(const ray &r,float t_min,float t_max,hit_record &rec) const;
protected:
vecfloat center;
float radius;
};
#endif
继承自我的抽象类的类是
sphere.h
#include "include/sphere.h"
bool sphere::hit(const ray &r,hit_record &rec) const
{
vecfloat oc = r.origin() - center;
float a = oc.dot_product(r.direction());
float b = oc.dot_product(oc) - radius * radius;
float c = oc.dot_product(oc) - radius * radius;
float discriminant = b * b - a * c;
if (discriminant > 0)
{
float temp = (-b - sqrt(b * b - a * c)) / a;
if (temp < t_max && temp > t_min)
{
rec.t = temp;
rec.p = r.point_at_parameter(rec.t);
rec.normal = (rec.p - center) / radius;
return true;
}
temp = (-b + sqrt(b * b - a * c)) / a;
if (temp < t_max && temp > t_min)
{
rec.t = temp;
rec.p = r.point_at_parameter(rec.t);
rec.normal = (rec.p - center) / radius;
return true;
}
}
return false;
}
sphere.cc
#ifndef HITTABLELIST_H
#define HITTABLELIST_H
#include "hittable.h"
class hittable_list : public hittable
{
public:
hittable_list() {}
hittable_list(hittable **l,int n)
{
list = l;
list_size = n;
}
bool hit(const ray &r,hit_record &rec) const;
~hittable_list() {}
protected:
hittable **list;
int list_size;
};
#endif
hittable.h
#include "include/hittablelist.h"
bool hittable_list::hit(const ray &r,hit_record &rec) const
{
hit_record temp_rec;
auto hit_anything = false;
auto closet_so_far = t_max;
for (int i = 0; i < list_size; i++)
{
if (list[i]->hit(r,t_min,closet_so_far,temp_rec))
{
hit_anything = true;
closet_so_far = temp_rec.t;
rec = temp_rec;
}
}
return hit_anything;
}
hittable.cc
{{1}}
解决方法
解决方案
更改
virtual ~hittable() = 0;
进入
virtual ~hittable() = default;
或
virtual ~hittable()
{
// does nothing
}
析构函数可以保持纯虚拟状态,但是必须具有定义。
hittable::~hittable()
{
// does nothing
}
那怎么了?
我们可以将给定的代码压缩为以下示例(请注意,我无法使用此代码或给定的代码来复制丢失的vtable
,但是无论如何,以上内容都可以解决此问题)
最小示例:
class hittable
{
public:
virtual ~hittable() = 0; // here we have a destructor,// but there's no implementation
// so there is nothing for the
// destructors of derived classes
// to call
virtual bool hit() const = 0;
};
class sphere: public hittable
{
public:
bool hit() const;
};
bool sphere::hit() const
{
return false;
}
析构函数调用任何基类的析构函数,并且当shpere
调用~hittable
时,它会发现声明了~hittable
时没有实现。没事了。