Udbhav Agarwal
Udbhav Agarwal

Reputation: 47

C++ : Error Redefinition & Previously Declared

I am half way into my course.I am unable to understand the logic behind the errors I am receiving. I have already tried to counter it by using appropriate directives at the bottom of my Array.h file. I am receive the following 2 errors across all functions:

  1. note: 'const T& udbhavAg::Container::Array::operator const' previously declared here const T &Array::operator[](int index) const {
  2. error: redefinition of 'const T& udbhavAg::Container::Array::operator const' const T &Array::operator[](int index) const {

My questions are the following :

  1. Why are the files being declared twice?
  2. Why are they being redefined?

Main.cpp

#include <iostream>
#include "Point.h"
#include "Line.h"
#include "Circle.h"
#include "Array.h"
#include "ArrayException.h"
using namespace std;
using namespace udbhavAg::CAD;
using namespace udbhavAg::Container;
using namespace udbhavAg;

int main()
{
    Array<Point> points(10);
    return 0;
}

Array.h

#include "Point.h"
#include <cstring>
#include "ArrayException.h"
#ifndef ARRAY_H
#define ARRAY_H
//#include "Array.cpp"

namespace udbhavAg
{
    namespace Container
    {
        template <typename T>
        class Array {
        private:
            T *m_data;
            int m_size;

        public:
            Array();

            Array(int size);

            Array(const Array &obj);

            virtual ~Array();

            //const Array operator= ( const Array & source);
            Array<T> &operator=(const Array &source);

            int Size() const;

            void setElement(int index, T p);

            T &getElement(int index) const;

            T &operator[](int index);

            const T &operator[](int index) const;
        };
    }
}

#ifndef Array_cpp // Must be the same name as in source file #define
#include "Array.cpp"
#endif

#endif ARRAY_H

Array.cpp

#include "Array.h"
#include "ArrayException.h"


namespace udbhavAg
{
    namespace Container
    {
        template<typename T>
        Array<T>::Array():m_size(3),m_data(new T[m_size]) {}

        template<typename T>
        Array<T>::Array(int size): m_size(size), m_data(new T[m_size]) {}

        template<typename T>
        Array<T>::~Array()
        {
            delete[] m_data;
            cout << "Destructor called" << endl;
        }

        template<typename T>
        Array<T>::Array(const Array &obj) {
            m_size = obj.m_size;

            m_data = new CAD::Point[m_size];

            for (int i = 0; i < m_size; i++)
            {
                m_data[i] = obj.operator[](i);
            }
        }

        template<typename T>
        int Array<T>::Size() const
        {
            return m_size;
        }

        template<typename T>
        T &Array<T>::getElement(int index) const
        {

            try
            {
                if (index >= m_size || index < 0)
                    {
                        throw (OutofBoundsException(index));
                    }
                else
                    {
                        return m_data[index];
                    }
            }
            catch (ArrayException &error)
            {
                cout << error.GetMessage();

            }

        }

        template<typename T>
        void Array<T>::setElement(int index, T p)
        {

            try
            {
                if (index >= m_size || index < 0)
                {
//                    OutofBoundsException error = OutofBoundsException(index);
//                    ArrayException& abc = error;
                    throw (OutofBoundsException(index));
                }
                else
                {
                    m_data[index] = p;
                }
            }
            catch (ArrayException &error)
            {
                cout << error.GetMessage();

            }

        }

        template<typename T>
        Array<T> & Array<T>::operator=(const Array &source)
                {
                    if(&source != this){ //edited self assignment test
                        if(m_size != source.m_size){//diff sized arrays
                            delete [] m_data; //reclaim space
                            m_size = source.m_size;
                            m_data = new CAD::Point[m_size]; //space created
                        }
                    }
                    for(int i=0; i<m_size; i++){
                        m_data[ i ] = source.m_data[i];}

                    return *this;     //enables cascading a=b=c
                }

        template<typename T>
        T &Array<T>::operator[](int index) {

            try
            {
                if (index >= m_size || index < 0)
                {
//                        OutofBoundsException error = OutofBoundsException(index);
//                        ArrayException& abc = error;
                    throw (OutofBoundsException(index));
                }
                else
                {
                    return m_data[index];
                }
            }
            catch (ArrayException &error)
            {
                cout << error.GetMessage();

            }
        }

        template<typename T>
        const T &Array<T>::operator[](int index) const {

            try
            {
                if (index >= m_size || index < 0)
                {
//                        OutofBoundsException error = OutofBoundsException(index);
//                        ArrayException& abc = error;
                    throw (OutofBoundsException(index));
                }
                else
                {
                    return m_data[index];
                }
            }
            catch (ArrayException &error)
            {
                cout << error.GetMessage();

            }
        }
    }
}

Upvotes: 0

Views: 1182

Answers (1)

bruno
bruno

Reputation: 32586

probably because in Array.h :

#ifndef Array_cpp // Must be the same name as in source file #define
#include "Array.cpp"
#endif

so Array.cpp #include Array.h whose #include Array.cpp because Array_cpp is not defined

Do not include source file in your header files

Out of that why in Array.h

#ifndef ARRAY_H
#define ARRAY_H

is not at the beginning of the file ?


So possible exclusive solutions to solve are :

  • to remove #include "Array.h" at the beginning of Array.cpp
  • to add #define Array_cpp to be the very first line in Array.cpp

in both case you must not compile Array.cpp in your Makefile or equivalent nor link with it.

But the best one is to replace in Array.h

#ifndef Array_cpp // Must be the same name as in source file #define
#include "Array.cpp"
#endif

by the definitions from the file Array.cpp and to delete the file Array.cpp.

The template classes are special, all template methods must be defined in the header file and only in it, not in a source file also compiled as a 'normal' source file, the compiler does the stuff for you

Upvotes: 3

Related Questions