2
votes

I have been implementing a custom Vector from one of the latest C++ books and I am coming upon an error in the vector.cpp and vector.h file at the Class Vector and Vector::Vector respectively: Redefinition of 'Vector'

Here is the code for each file:

main.cpp:

#include <iostream>
#include "Vector.h"
#include "Container.h"

int main(int argc, const char * argv[]) {
    return 0;
}

vector.h

class Vector {
public:
    Vector(int s) :elem{new double[s]}, sz{s}     // constructor: acquire resources
    {
        for (int i=0; i!=s; ++i)      // initialize elements
            elem[i]=0;
            }

    ~Vector() { delete[] elem; }                  // destructor: release resources

    double& operator[](int i);
    int size() const;
private:
    double* elem;     // elem points to an array of sz doubles
    int sz;
};

vector.cpp

Vector::Vector(int s) // definition of the constructor

:elem{new double[s]}, sz{s} // initialize members
{}
double& Vector::operator[](int i) // definition of subscripting
{
    return elem[i];
}

int Vector::size() const // definition of size()
{
    return sz;
}

container.cpp

class Container {
public:
     virtual double& operator[](int) = 0;     // pure virtual function
     virtual int size() const = 0;            // const member function (§4.2.1)
     virtual ~Container() {}                  // destructor (§4.2.2)
};


class Vector_container : public Container {   // Vector_container implements Container
public:
     Vector_container(int s) : v(s) { }   // Vector of s elements
     ~Vector_container() {}

     double& operator[](int i) override { return v[i]; }
     int size() const override { return v.size(); }
private:
     Vector v;
};

I tried enclosing the .h file with #ifndef Vector_h,#define Vector_h, and #endif but it the error still appears in Vector_cpp. If I encapsulate Vector.cpp with #ifndef Vector_cpp, #define Vector_h, and #endif the error still appears.

To add insult to injury, when I add Vector.h to container.cpp it tells me: Unknown type name 'Vector' at the bottom where I declared Vector v

Can anyone help me with this?

2
Here is the header file for the container? :)gsamaras
You do need the #ifndef's for sure, in each header file. Where is your Container.h?ChrisMM
You implemented the Vector::Vector(int s) constructor in both the header and the .cpp file. Choose one. If your choice is the .cpp file, then strip the body and member initialization list of Vector(int s)` from the header, leaving only the decl in the header; just like you did with the size() member.WhozCraig
I didn't make a header file for the container. Oops!Lester
You're defining the ctor both in the header and in the source file. Delete the definition in the header.o11c

2 Answers

2
votes

You need to implement a header file for your Container class as well, so you need a Container.h too (note this should match the name of the file). In your case, it seems that it would suffice to just rename your file, from Container.cpp, to Container.h.

Moreover, you should implement your methods (e.g. the constructor of Vector) into only one file, not two. For example, you would declare the method in the header file, and then define it in the source file.


Putting everything together, you need:

  • main.cpp (no changes here)
  • Container.h (and not Container.cpp, but no changes in the content of the file, you did a good work! :))
  • Vector.h

    class Vector {
    public:
        Vector(int s);
    
        ~Vector();
        double& operator[](int i);
        int size() const;
    private:
        double* elem;     // elem points to an array of sz doubles
        int sz;
    };
    
  • Vector.cpp

    #include "Vector.h"
    
    Vector::Vector(int s) :elem{new double[s]}, sz{s} // initialize members
    {}
    double& Vector::operator[](int i) // definition of subscripting
    {
        return elem[i];
    }
    
    int Vector::size() const // definition of size()
    {
        return sz;
    }
    
    Vector::~Vector() { delete[] elem; } 
    

Compile:

g++ main.cpp Vector.cpp

1
votes
  1. .Common practice is following project structure below (using guards directives):

ClassName1.h

#ifndef CLASSNAME1_H
#define CLASSNAME1_H

// class definition
class ClassName1
{
     // ...
};

#endif

ClassName1.cpp

#include "ClassName1.h"

// implementation of ClassName1 functions may go here - except templates - templates should be defined eventually in one header file (not separate compilation unit) or one header with template body may include implementation from second header with implementation if template is big enough- extension , say - ipp. At least this is limitation for C++98.
ClassName1::someFunction()
{
    // ...
}

Main.cpp // or some other user code that uses ClassName1

#include "ClassName1.h"

ClassName1::someStaticFunction(); // for instance
ClassName1 className1; // for instance

Following this structure systematically with all classes you won't encounter class redefinition. this makes code portable.

2.There is another non standard way (Visual C++, GCC) - using : #pragma once directive

#pragma once

struct foo {
    int member;
};