简体   繁体   中英

undefined reference to vtable with all virtual functions implemented

I have these two structs defined:

#ifndef OBJECT_H_
#define OBJECT_H_
#include <stdio.h>
#include "vector.h"

struct object{
public:
    int index;               // identifies a object; must be greater than 0
    float mat_ambient[3];    // material property used in Phong model
    float mat_diffuse[3];
    float mat_specular[3];
    float mat_shineness;
    float reflectance;       // this number [0,1] determines how much
                             // reflected light contributes to the color
                             // of a pixel
    virtual float intersect(Point, Vector, object*, Point*);
    virtual Vector normal(Point, object*);
};
#endif /* OBJECT_H_ */

#ifndef SPHERE_H_
#define SPHERE_H_

#include "object.h"

struct sphere: public object {
public:
    Point center;
    float radius;

    // intersect ray with sphere
    float intersect(Point, Vector, object*, Point*);
    // return the unit normal at a point on sphere
    Vector normal(Point, object*);
};
#endif /* SPHERE_H_ */

However, when I try to compile, I get these two errors:

undefined reference to `vtable for object'

I know it's not my makefile, as it already added sphere.cpp and object.cpp Is there a function or a method missing from my structs that's causing this?

object.cpp

#include "object.h"

#include <stdlib.h>
#include <math.h>
#include <iostream>
#include "sphere.h"

using namespace std;

/**********************************************************************
 * This function intersects a ray with a given sphere 'sph'. You should
 * use the parametric representation of a line and do the intersection.
 * The function should return the parameter value for the intersection,
 * which will be compared with others to determine which intersection
 * is closest. The value -1.0 is returned if there is no intersection
 *
 * If there is an intersection, the point of intersection should be
 * stored in the "hit" variable
 **********************************************************************/
float sphere::intersect(Point A, Vector p, object *o, Point *hit) {
    cout << "intersect" << endl;
    sphere* s = (sphere*) o;
    Point C = s->center;
    Point B;
    B.x = A.x + p.x;
    B.y = A.y + p.y;
    B.z = A.z + p.z;

    float a = pow(B.x - A.x, 2) + pow(B.y - A.y, 2) + pow(B.z - A.z, 2);
    float b = 2 * ((B.x - A.x) * (A.x - C.x) + (B.y - A.y) * (A.y - C.y) + (B.z - A.z) * (A.z - C.z));
    float c = pow(A.x - C.x, 2) + pow(A.y - C.y, 2) + pow(A.z - C.z, 2) - pow(s->radius, 2);

    float delta = pow(b, 2) - 4 * a * c;

    if (delta < 0.0) {
        //no intersection
        return -1.0;
    }
    if (delta >= 0.0) {
        //possibly more then one intersection, but at least one, return the smallest one
        float d1 = (-b - sqrt(delta)) / (2 * a);
        float d2 = (-b + sqrt(delta)) / (2 * a);
        if (d1 < d2) {
            hit->x = A.x + (p.x * d1);
            hit->y = A.y + (p.y * d1);
            hit->z = A.z + (p.z * d1);
            return d1;
        } else {
            hit->x = A.x + (p.x * d2);
            hit->y = A.y + (p.y * d2);
            hit->z = A.z + (p.z * d2);
            return d2;
        }
    }
    return -1.0;
}
/******************************************
 * computes a sphere normal - done for you
 ******************************************/
Vector sphere::normal(Point q, object *o) {
    sphere *sph =  (sphere *) o;
    Vector rc;

    rc = get_vec(sph->center, q);
    normalize(&rc);
    return rc;
}

Makefile

#! /usr/bin/make

SOURCE= scene.cpp image_util.cpp sphere.cpp vector.cpp trace.cpp raycast.cpp object.cpp include/InitShader.cpp

CC= g++

CFLAGS= -O3 -ggdb -O0  -Wall -pedantic -DGL_GLEXT_PROTOTYPES -std=c++11

EXECUTABLE= raycast

LDFLAGS = -lGL -lglut -lGLEW -lXext -lX11 -lm

INCLUDEFLAG= -I. -I$(INCLUDEDIR) -Iinclude/
LIBFLAG= -L$(LIBDIR)

OBJECT= $(SOURCE:.cpp=.o)

all: $(OBJECT) depend
    $(CC) $(CFLAGS) $(INCLUDEFLAG) $(LIBFLAG)  $(OBJECT) -o $(EXECUTABLE) $(LDFLAGS)

depend:
    $(CC) -M $(SOURCE) > depend

$(OBJECT):
    $(CC) $(CFLAGS) $(INCLUDEFLAG) -c -o $@ $(@:.o=.cpp)

clean_object:
    rm -f $(OBJECT)

clean:
    rm -f $(OBJECT) depend $(EXECUTABLE)

include depend
undefined reference to `vtable for object'

You are getting this error because you have not provided definition of virtual method in object. Basically vtable stores function pointers ie address of virtual function is required. So if you miss the definition of single virtual function, compiler won't be able to generate complete vtable for that class.

For your object class vtable would be like something:-

&object::intersect
&object::normal

EDIT:-

That means corresponding to these:-

virtual float intersect(Point, Vector, object*, Point*);
virtual Vector normal(Point, object*);

You should have :-

float object::intersect(Point, Vector, object*, Point*)
{
}

Vector object::normal(Point, object*)
{
}

If there's no definition for object::intersect & object::normal, you should make them pure virtual functions as below:

#ifndef OBJECT_H_      
#define OBJECT_H_
#include <stdio.h>
#include "vector.h"

struct object{
public:
    int index;               // identifies a object; must be greater than 0
    float mat_ambient[3];    // material property used in Phong model
    float mat_diffuse[3];
    float mat_specular[3];
    float mat_shineness;
    float reflectance;       // this number [0,1] determines how much reflected light contributes to the color of a pixel
    virtual float intersect(Point, Vector, object*, Point*) = 0;
    virtual Vector normal(Point, object*) = 0;
};
#endif /* OBJECT_H_ */

Try it and I think it would figure out your problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM