未定义对vtable和抽象类的引用

问题描述

构建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时没有实现。没事了。