-2

I am trying to create a class template inheriting from another class template, the first being a class containing nothing but pure virtual methods, and the second one being the one that's going to be manipulated. What I am trying to build is a vector class that has a size determined by the second template argument. The base class will serve to create another vector class whose size will be different for each object of the class.

After fiddling around for 2-3 days, I can't figure out how to fix a series of errors that occur when I try to compile the project.

Here is the header (Vect.hpp)

#ifndef NEWFILE1_HPP
#define NEWFILE1_HPP

#include <cstddef>    
#include <iostream>    
#include <exception>
#include <stdexcept>   

template <class elem>
class Vect
{
    public:          
        virtual elem& operator[] (std::ptrdiff_t nIndex) =0;
        virtual const elem& operator[] (std::ptrdiff_t nIndex) const =0;
        virtual Vect& operator+() =0;
        virtual Vect& operator-() =0;
        virtual Vect& operator+(const elem&) =0;
        virtual Vect& operator-(const elem&) =0;
        //virtual Vect& operator*(const elem&) =0;

        virtual ~Vect();

};


template <class elem, std::size_t taille=10>

class Vect_fixe: public Vect<elem>
{
    template <typename T, std::size_t D>
        friend std::ostream& operator<< (std::ostream&, const Vect_fixe<T, D>&);

    public:
    Vect_fixe():vecteur(new elem[taille]) {};
    virtual elem& operator[] (std::ptrdiff_t nIndex);
    virtual const elem& operator[] (std::ptrdiff_t nIndex) const;
    virtual Vect_fixe& operator+();
    virtual Vect_fixe& operator-();
    virtual Vect_fixe& operator+(const elem&);
    virtual Vect_fixe& operator-(const elem&);


    private:
    elem vecteur[taille];
    ~Vect_fixe(){delete[] vecteur;}
};

and here is the one defining the functions and doing the tests (main.cpp)

#include <cstdlib>
#include "Vect.hpp"
#include <exception>
#include <stdexcept>   

template <class elem, std::size_t taille>
elem& Vect_fixe<elem, taille>::operator[] (std::ptrdiff_t nIndex)
{
    if (nIndex >= taille)
        throw std::out_of_range("Index out of range.");
    return vecteur[nIndex];

};

template <class elem, std::size_t taille>
const elem& Vect_fixe<elem, taille>::operator[] (std::ptrdiff_t nIndex) const
{
    if (nIndex >= taille)
        throw std::out_of_range("Index out of range.");
    return vecteur[nIndex];

};

template <class elem, std::size_t taille>
Vect_fixe<elem, taille>& Vect_fixe<elem, taille>::operator +()
{
    return *this;
}

template <class elem, std::size_t taille>
Vect_fixe<elem, taille>& Vect_fixe<elem, taille>::operator -()
{
    Vect_fixe<elem, taille> temp_v;
    for (int i=0; i<taille; i++)
        temp_v[i] = -temp_v[i];
    return temp_v;
}

template <class elem, std::size_t taille>
Vect_fixe<elem,taille>& Vect_fixe<elem, taille>::operator+(const elem&)
{
    Vect_fixe<elem, taille> temp_v;
    elem obj;
    for (int i=0; i<taille; i++)
        temp_v[i] += obj;
    return temp_v;
}

template <class elem, std::size_t taille>
Vect_fixe<elem,taille>& Vect_fixe<elem, taille>::operator-(const elem&)
{
    Vect_fixe<elem, taille> temp_v;
    elem obj;
    for (int i=0; i<taille; i++)
        temp_v[i] -= obj;
    return temp_v;
}


int main() {

    int x;
    x = 5;
    Vect_fixe<int, 10> vect;
    //std::cout<< vect << std::endl;



    return 0;
}

And the error I get is the following:

g++ -std=c++14    -o dist/Debug/Cygwin_4.x-Windows/cppapplication_2 build/Debug/Cygwin_4.x-Windows/Vect.o build/Debug/Cygwin_4.x-Windows/main.o 
build/Debug/Cygwin_4.x-Windows/main.o: In function `Vect_fixe<int, 10ul>::~Vect_fixe()':
/cygdrive/e/University/BA2/Langages de Programmation/Projet C++/CppApplication_2/Vect.hpp:48: undefined reference to `Vect<int>::~Vect()'
/cygdrive/e/University/BA2/Langages de Programmation/Projet C++/CppApplication_2/Vect.hpp:48:(.text$_ZN9Vect_fixeIiLm10EED1Ev[_ZN9Vect_fixeIiLm10EED1Ev]+0x3f): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `Vect<int>::~Vect()'
collect2: error: ld returned 1 exit status

What lead to this state was me trying to fix a previous error that was the return of a reference to a local variable. I put the const keyword in some functions, but that didn't seem to fix the problem so I reverted, and this is what happened. The error is really unclear to me, probably because I am used to programming in Python where almost every error is explained.

Iocust
  • 105
  • 1
  • 14
  • You should stick to one question per post. – juanchopanza Nov 26 '15 at 16:12
  • @juanchopanza Well technically, there is only one question, I was just giving the context in which it occurred. But yes, perhaps the title I chose wasn't the best. – Iocust Nov 26 '15 at 16:15
  • Your error is not a compiler error but a linker error. You basically makes `g++ -std=c++14 -o Vect.o main.o`, which is a non-sense. There is a missing executable name, here you are linking main.o INTO Vect.o. Your link command should looks like `g++ -o myApp Vect.o main.o`. If it is a Makefile generated chain, please check it; if it is an IDE then you must carefully check the build chain. – Jean-Baptiste Yunès Nov 26 '15 at 16:16
  • 1
    Your Vect destructor need a a body somewhere. – Neil Kirk Nov 26 '15 at 16:18
  • 2
    Technically, there is no question here. But you seem to be asking about two distinct problems. – juanchopanza Nov 26 '15 at 16:18
  • @Jean-BaptisteYunès I see! Yes I am using NetBeans, so I guess I will just compile it without the IDE, see if it changes anything. – Iocust Nov 26 '15 at 16:19
  • Well you've probably make a serious mistake while configuring your project in Netbeans... Or maybe some blank field somewhere??? Very strange to me, at least. It is in general difficult to fool IDEs like this! – Jean-Baptiste Yunès Nov 26 '15 at 16:21
  • @Jean-BaptisteYunès I think the only thing I changed was adding -std=c++14, since I wanted to use the latest version. – Iocust Nov 26 '15 at 16:23
  • Don't bother on c++14, it doesn't seems that you are actually using c++14 constructions. Anyway, also implements the Vector dtor...even if empty. You need to declare it to make it virtual so you need to define it. – Jean-Baptiste Yunès Nov 26 '15 at 16:27
  • @Jean-BaptisteYunès Alright! Thanks for the assistance :) – Iocust Nov 26 '15 at 16:30

2 Answers2

4
  1. Some of your functions (e.g. operator -())are returning references to stack-allocated variables. These will go out of scope once the functions exits.

That's undefined behaviour.

The remedy is to return a value copy. Drop the reference return type from the function.

  1. You need to provide an implementation for ~Vect() and ~Vect_fixe(). If they are not needed then don't declare them in the class.
Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • Thank you for your swift answer! I suppose that by reference return type you mean that I am returning the temporary variables I created? I understand, but in that case would you suggest directly modifying the object? I don't see another way of returning a modified version of it. – Iocust Nov 26 '15 at 16:13
  • Indeed, you cannot return a temporary variable by reference. If you can return the modified `this` then returning `*this` as a reference is fine. – Bathsheba Nov 26 '15 at 16:15
2

You forgot to implement the destructor for Vect and you should implement the destructor for Vect_fixe in your cpp file. That will remove your undefined reference to your destructors.

Your error reference to a local variable should be fixed if you change the return type of the operator-from Vect& to Vect. You can't return a reference to a local variable. That's undefined behaviour.

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141