Forward Declaration Mis-Match

Well, I've run into a snag. I have two classes that rely heavily on each other through references in particular functions. In fact, when I forward-declare both of them in each other's files, I get an error telling me that I am incorrectly using incomplete classes, and shouldn't forward-declare. Issue is, if I include both classes in one-another, it doesn't work either. So what do I do? The code, for reference:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#ifndef VERTEX_H
#define VERTEX_H
#include <memory>
#include <utility>
#include <unordered_set>

class Connector;

class Vertex
{
    public:
        Vertex();
        ~Vertex();
        Vertex(const Vertex& other);
        Vertex& operator=(const Vertex& other);
        bool operator==(const Vertex&) const;
        std::unordered_set<Connector**> connection_set;
        unsigned int get_state() const {return state;}
        void set_state(unsigned int state) {this->state = state;}
        void boundary(const unsigned int);
    protected:
    private:
        unsigned int state;
        std::pair<int,int>coordinates;

};



namespace std
{
    template <>
        class hash<Vertex>{
        public :
        size_t operator()(const Vertex &v ) const{
            return hash<Vertex>()(v)/sizeof(Vertex);
        }
    };
}
#endif // VERTEX_H 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include "Vertex.h"

Vertex::Vertex()
    : state(0)
    , coordinates(0,0)
{
    //ctor
}

Vertex::~Vertex()
{
    //dtor
}

Vertex::Vertex(const Vertex& other)
    : state(other.state)
    , coordinates(other.coordinates)
{

}

Vertex& Vertex::operator=(const Vertex& rhs)
{
    if (this == &rhs) return *this; // handle self assignment
    this->state = rhs.state;
    return *this;
}

bool Vertex::operator==(const Vertex& rhs) const
{
    if(this->state == rhs.get_state())
    {
        if(this->connection_set.size() == rhs.connection_set.size())
        {
            for(std::unordered_set<Connector**>::const_iterator i = this->connection_set.begin(); i != this->connection_set.end();i++)
                {
                    if(rhs.connection_set.find(*i) == rhs.connection_set.end())
                        return false;
                    return true;
                }
        }
        else
            return false;
    }
    return false;
}

void Vertex::boundary(const unsigned int base)
{
    unsigned int temp_state = state;
    for(std::unordered_set<Connector**>::const_iterator i = this->connection_set.begin(); i != this->connection_set.end();i++)
        temp_state += (**i)->get_state();

}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#ifndef CONNECTOR_H
#define CONNECTOR_H
#include <memory>
#include <utility>
#include <unordered_set>
#include "Vertex.h"

class Connector
{
    public:
        Connector();
        Connector(Vertex**,Vertex**);
        ~Connector();
        Connector(const Connector& other);
        Connector& operator=(const Connector& other);
        const std::pair<Vertex**,Vertex**> vertex_pair;
        unsigned int get_state() const {return state;}
        void set_state(unsigned int state) {this->state = state;}
        void coboundary(const unsigned int);
    protected:
    private:
        unsigned int state;
};

namespace std
{
    template <>
        class hash<Connector*>{
        public :
        size_t operator()(const Connector &c ) const{
            return hash<Vertex**>()(c.vertex_pair.first) ^ hash<Vertex**>()(c.vertex_pair.second);
        }
    };
}
#endif // CONNECTOR_H 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include "Connector.h"

Connector::Connector()
    : vertex_pair(std::make_pair(nullptr,nullptr))
    , state(0) {}

Connector::Connector(Vertex** v1,Vertex** v2)
    : vertex_pair(std::make_pair(v1,v2))
    , state(0)
{

}
Connector::~Connector()
{
    if(vertex_pair.first == nullptr)
        return;
    if(vertex_pair.second == nullptr)
        return;
    auto * a = vertex_pair.first;
    auto * b = vertex_pair.second;
    for ( auto p : (*a)->connection_set)
        if (*p == this)
            (*a)->connection_set.erase(p);
    for ( auto p : (*b)->connection_set)
        if (*p == this)
            (*b)->connection_set.erase(p);
}

Connector::Connector(const Connector& other)
    : vertex_pair(other.vertex_pair)
    , state(other.state) {}

Connector& Connector::operator=(const Connector& rhs)
{
    if (this == &rhs) return *this; // handle self assignment
    this->state = rhs.state;
    return *this;
}

void Connector::coboundary(const unsigned int base)
{
    auto * a = vertex_pair.first;
    auto * b = vertex_pair.second;
    state = ((*a)->get_state() + (*b)->get_state()) % base;
}
Could you combine both classes into one class?
I cannot. You see, a connector can only have two vertices as its endpoints, while a vertex can have several connectors attached to it. When a connector is deleted, its reference in each vertex is removed; however, when a vertex is deleted, all connecting connectors too are deleted. Because of this behavior, they cannot be the same object- it would cause way too many complications.
Nevermind, solved it myself- turns out that you can include one class's header in the other's implementation file with no problems whatsoever.
Topic archived. No new replies allowed.