Bob Maza
Bob Maza

Reputation: 59

c++ template abstract inheritance

I'm student in my final year for my masters degree in computer graphics we had to do an exercise in C++.

Here is the code :

AbsMatrice.h:

#pragma once

template<int M,int N, typename T>
class AbsMatrice
{
private:

T m_data[M][N];

public:
AbsMatrice();
~AbsMatrice();

AbsMatrice<M, N, T> mul(AbsMatrice<M,N,T> &a);
AbsMatrice<M, N, T> add(AbsMatrice<M, N, T> &a);
void read(...);

T& at(int row, int col);
T& operator ()(int row, int col);

//fonction virtuelle pure
virtual void print() = 0;

int& getNumRows(){ return M; }
int& getNumColumns(){ return N; }
};

Matrice.h:

#pragma once
#include "AbsMatrice.h"

template <int M, int N, typename T>

class Matrice : public AbsMatrice<M,N,T>
{

public:
    Matrice();
    ~Matrice();

    void print();
 };

AbsMatrice.cpp:

#include "AbsMatrice.h"
#include <iostream>


template<int M, int N, typename T>
AbsMatrice<M, N, T>::AbsMatrice(){
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        {
            m_data[i][j] = 0;
        }
    }
}

template<int M, int N, typename T>
AbsMatrice<M, N, T>::~AbsMatrice()
{
}

template<int M, int N, typename T>
T& AbsMatrice<M, N, T>::operator ()(int row, int col)
{
    return m_data[row][col];
}

template<int M, int N, typename T>
T& AbsMatrice<M, N, T>::at(int row, int col)
{
    return m_data[row][col];
}

template<int M, int N, typename T>
AbsMatrice<M, N, T> AbsMatrice<M, N, T>::add(AbsMatrice<M, N, T> &a)
{
    if (this->getNumColumns() == a.getNumColumns() && this->getNumRows() == a.getNumRows())
    {
        for (int i = 0; i < M; i++)
        {
            for (int j = 0; j < N; j++)
            {
                m_data[i][j] += a(i, j);
            }
        }
    }
    else
        std::cout << "Erreur matrice de taille différentes !" << std::endl;

    return this;
}

template<int M, int N, typename T>
void AbsMatrice<M, N, T>::print()
{
    std::cout << "la matrice :" << std::endl;
}

Matrice.cpp:

#include "Matrice.h"
#include <iostream>


template <int M, int N, typename T>
Matrice<M,N,T>::~Matrice()
{
}

template <int M, int N, typename T>
void Matrice<M, N, T>::print()
{
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        {
            std::cout << " " << this->m_data[i][j] << " ";
        }
        std::endl;
    }
}

when I try to do this in main:

main.cpp:

#include "Matrice.h"


int main()
{
    Matrice<2,2,int> a;
    Matrice<2,2,int> b;

}

I get a nasty:

error C2259: 'AbsMatrice<2,2,T>' : cannot instantiate abstract class
1>          with
1>          [
1>              T=int
1>          ]
1>          due to following members:
1>          'void AbsMatrice<2,2,T>::print(void)' : is abstract
1>          with
1>          [
1>              T=int
1>          ]
1>          c:\users\bobmaza\documents\visual studio 2013\projects\tpmatrices\tpmatrices\absmatrice.h(22) : see declaration of 'AbsMatrice<2,2,T>::print'
1>          with
1>          [
1>              T=int
1>          ]

I tried searching everywhere on the web , but did not find a case close to mine and most of the guys did not use the same signature to override the abstract function, but it is not my case. I never seen an error like this thank you in advance.

What is the meaning of the error message and how to correct it?

Note: I have been coding in c++ in several years but never had to do something like this , so I can't figure it out !

P.S. : Sorry for the French names I'm a student in France.

EDIT : thanks to everyone for the help , first time i HAD to ask arround here , great community !

Upvotes: 1

Views: 71

Answers (4)

Konstantin Baluev
Konstantin Baluev

Reputation: 46

The compiler tells you exactly what is happening - void Matrice<M,N,T>::print() is not declared virtual thus leading to pure virtual function virtual void print() = 0 not to be overloaded.

To avoid this in future, specify the overloading (virtual) functions as override.

Moreover, I assume the print function to not modify the internal state of the object and to work all the time, so the const noexcept specifier would be appropriate.

Here is a snippet which might help you with the safer virtual functions overloading

class Interface
{
public:
   virtual ~Interface() {}
   virtual void print() const noexcept = 0;
};

class Implementation : public Interface
{
public:
   virtual ~Implementation() {}
   virtual void print() const noexcept override
   {
      ...
   }
};
  • When a looser throw specifier is declared in the overloading function, the error is fired.
  • When a looser internal state specifier is declared in the overloading function, the error is fired.
  • When an overriding function does not override, the error is fired.

Upvotes: 0

Dimitrios Bouzas
Dimitrios Bouzas

Reputation: 42899

First of, since AbsMatrice is pure virtual you can't return by value an abstract type, so you must return either a reference or pointer:

AbsMatrice<M, N, T>& mul(AbsMatrice<M, N, T> &a);
                   ^
AbsMatrice<M, N, T>& add(AbsMatrice<M, N, T> &a);
                   ^

Secondly, destructor of a base class must be declared virtual to avoid potentially memory leaks.

virtual ~AbsMatrice();

Upvotes: 0

king_nak
king_nak

Reputation: 11513

Templates must always be completely defined, as the compiler will generate an implementation whenever a template is instantiated, with the concrete template parameters specified. Therefore, all method bodies must be available wherever a template is used. That's why template classes / libraries are often contained in a single .hpp file.

What does this mean for your case? Even if there is a template implementation for Matrice<int,int,typename>::print() in some .cpp file, the compiler does not see it when compiling main.cpp. Therefore it cannot generate an implementation for Matrice<2,2,int>::print(), and thus, there is no definition of that method. All it sees is virtual AbsMatrice::print() = 0;

Upvotes: 0

Eric
Eric

Reputation: 97571

You need to define your function, not just declare it:

virtual void print() {}

Upvotes: 1

Related Questions