1

Marca referencia indefinida en v table
Hice una clase padre, que es vehículos, el cual es heredado por dos clases hija. Cuando no incluyo las clases hijas el programa compila y genera el *.exe.
Pero cuando incluyo las dos clases hijas manda este error: (.text$ZN9VehiculosC2EPcS0_S0_S0_S0[_ZN9VehiculosC2EPcS0_S0_S0_S0]+0xa): undefined reference to `vtable for Vehiculos'
collect2.exe: error: ld returned 1 exit status
Ya busque e hice de nuevo mi código, pero aun así me marca error.
Esta es mi clase padre:

#ifndef __VEHICULOS_H__

#define __VEHICULOS_H__

class Vehiculos
{
protected:
    char *nombreCom;
    char *nombreP;
    char *origen;
    char *destino;
    char *FechaS;
    long double CostoTotal;

public:
    Vehiculos(char *nombreCom, char *nombreP, char *origen, char *destino, char *FechaS)
    {
        this->nombreCom = nombreCom;
        this->nombreP = nombreP;
        this->origen = origen;
        this->destino = destino;
        this->FechaS = FechaS;
        this->CostoTotal = 0;
    };
    virtual long double CalcularPresioTotal(float);
};

#endif 

Estas son mis clases hijas:

#ifndef __TAXI_H__
#define __TAXI_H__

#include "Vehiculos.h"

class Taxi : public Vehiculos
{
private:
    char *matricula;

public:
    Taxi(char *);
    ~Taxi();
    long double CalcularPresioTotal(float);
};
Taxi::Taxi(char *matricula) : Vehiculos(nombreCom, nombreP, origen, destino, FechaS)
{
    this->matricula = matricula;
}

Taxi::~Taxi()
{
}
long double Taxi::CalcularPresioTotal(float kmrecorridos)
{
    this->CostoTotal = kmrecorridos * 1;
    return (this->CostoTotal += 20);
}
#endif

#ifndef __AVION_H__

#define __AVION_H__

#include "Vehiculos.h"

enum Categorys
{
    PrimeraClase = 1,
    ClaseTurusta = 2
};

class Avion : public Vehiculos
{
private:
    char *NumV = new char[6];
    char *asiento = new char[2];
    Categorys categoria;

public:
    Avion(char *, char *, Categorys);

    ~Avion();
    long double CalcularPresioTotal(float);
};
Avion::Avion(char *NumV, char *asiento, Categorys categoria) : Vehiculos(nombreCom, nombreP, origen, destino, FechaS)
{
    this->NumV = NumV;
    this->asiento = asiento;
    this->categoria = categoria;
}

Avion::~Avion()
{
}
long double Avion::CalcularPresioTotal(float kmrecorridos)
{
    this->CostoTotal = kmrecorridos * 3;
    return (this->CostoTotal += this->CostoTotal);
}
#endif

#ifndef __AUTOMOVIL_H__
#define __AUTOMOVIL_H__

#include "Vehiculos.h"

enum TypePasangers
{
    nino = 1,
    adulto = 2,
    mayor = 3
};

class Autobus : Vehiculos
{
private:
    TypePasangers tipoDePasagero;
    int NumAsiento;

public:
    Autobus(TypePasangers, int);
    ~Autobus();
    long double CalcularPresioTotal(float);
};

Autobus::Autobus(TypePasangers tipoDePasagero, int NumAsiento) : Vehiculos(nombreCom, nombreP, origen, destino, FechaS)
{
    this->tipoDePasagero = tipoDePasagero;
    this->NumAsiento = NumAsiento;
}

Autobus::~Autobus()
{
}

long double Autobus::CalcularPresioTotal(float kmRecorridos)
{
    if (this->tipoDePasagero == TypePasangers::mayor)
    {
        this->CostoTotal = (kmRecorridos * 2) / 2;
    }
    else
    {
        this->CostoTotal = kmRecorridos * 2;
    }
    return this->CostoTotal;
}

#endif
  • Ese error es **de enlazado**. Eso quiere decir que tu programa compila bien, pero falla en el siguiente paso, al construir el ejecutable. ¿ Como **exactamente** lo estás compilando ? – Trauma May 12 '21 at 03:45
  • Estoy usando el debugger de code, con mingW, usa el g++. Aveces yo pongo este codigo `g++ -o main main.cpp`. La version de mingW es 8.1.0 – Daniel Gonzaléz Martínez May 12 '21 at 04:12
  • La compilación son dos pasos: compilación y enlazado, en el enlazado tienes que referenciar todo el código objeto que has generado en la compilación (todos los .o) – eferion May 12 '21 at 06:52

1 Answers1

0

Un pequeño error que estás cometiendo:

En C++, cuando trabajes con clases virtuales y herencia, asegúrate que los destructores de las clases padre son virtuales.

Si no es así y usas polimorfismo acabarás inevitablemente con fugas de memoria:

class Vehiculos
{
public:
    virtual ~Vehiculos() = default;
};

Es facil demostrar el problema que se crea si se te olvida este detalle:

class Mal1
{
public:
    ~Mal1()
    { std::cout << "Este destructor no se invoca nunca!!!\n"; }
};

class Mal2 : public Mal1
{
public:
    ~Mal2()
    { std::cout << "Mal2::~Mal2()\n"; }
};

class Bien1
{
public:
    virtual ~Bien1()
    { std::cout << "Bien1::~Bien1()\n"; }
};

class Bien2 : public Bien1
{
public:
    ~Bien2()
    { std::cout << "Bien2::~Bien2()\n"; }
};

int main()
{
    Mal1 * mal = new Mal2;
    delete mal;

    Bien1 * bien = new Bien2;
    delete bien;
}

Puedes ver el ejemplo funcionando aquí

En cualquier caso tu problema es, como te estamos diciendo, que durante la fase de enlazado no estás referenciando todos los archivos de código objeto:

g++ -o app main.o Autobus.o Avion.o Taxi.o Vehiculos.o

Fíjate que los archivos de los que dependen los demás van al final

g++ -o app [más dependencias] ... [sin dependencias]
eferion
  • 49,291
  • 5
  • 30
  • 72
  • Ya genere mi destructor y aun asi sigue mandando el mismo error, tambien estoy poniendo todos los archivos _g++ -o main main.cpp models/Vehiculos.h models/Autobus.h models/Avion.h models/Taxi.h_ Y me manda esto: **C:\Users\danie\AppData\Local\Temp\ccsKO4HD.o:main.cpp:(.text$_ZN9VehiculosC2EPcS0_S0_S0_S0_[__ZN9VehiculosC2EPcS0_S0_S0_S0_]+0xa): undefined reference to `vtable for Vehiculos' C:\Users\danie\AppData\Local\Temp\ccsKO4HD.o:main.cpp:(.text$_ZN9VehiculosD2Ev[__ZN9VehiculosD2Ev]+0xa): undefined reference to `vtable for Vehiculos' collect2.exe: error: ld returned 1 exit status** – Daniel Gonzaléz Martínez May 12 '21 at 16:26