Код организации - PullRequest
       15

Код организации

0 голосов
/ 02 мая 2018

У меня есть реализация этого шаблона посетителя:

class Visitor {
  public:
    Visitor() {}
    void visit(A *a){ a->doSomething(); }
    void visit(B *b){ b->doSomething(); }
};

class Base {
  public:
    Base() {}
    virtual void accept(Visitor *v) = 0;
};

class A: public Base {
  public:
    A():Base() {}
    void accept(Visitor *v) override { v->visit(this) };
    .....
};

class B: public Base {
  public:
    B():Base() {}
    void accept(Visitor *v) override { v->visit(this) };
};

Проблема в том, что A и B имеют неполные типы в реализации Visitor. Но я не хочу помещать реализацию в отдельный исходный файл.

Есть ли способ поместить его в один заголовочный файл?

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

Переслать декларацию A и B. Переместите свои visit(A*a); и visit(B*b); за пределы объявления класса посетителя и объявите его после A и B классов. Чтобы избежать дублирования символов, поместите это в заголовочный файл, например, Header.h:

//forward declarations
class A;
class B;

class Visitor {
public:
    Visitor() {}
    void visit(A *a);
    void visit(B *b);
};

class Base {
public:
    Base() {}
    virtual void accept(Visitor *v) = 0;
};

class A: public Base {
public:
    A():Base() {}
    void accept(Visitor *v) override { v->visit(this); };
    void doSomething(){};
};

class B: public Base {
public:
    B():Base() {}
    void accept(Visitor *v) override { v->visit(this); };
    void doSomething(){};
};

Это объявление должно быть помещено в файл cpp, чтобы избежать дублирования символов, например, добавьте его в main.cpp:

#include "Header.h"

//outside declarations of methods
void Visitor::visit(A *a){ a->doSomething(); }
void Visitor::visit(B *b){ b->doSomething(); }
0 голосов
/ 02 мая 2018

Суть:

Пока у вас есть два класса (например, A и Visitor), и для реализации каждого из них требуется объявление другого, вы не можете объединить реализацию и объявление.

В вашем случае:

class Visitor {
public:
    // Visitor's implementation needs A's declaration
    void visit(A *a){ a->doSomething(); }
};

class A {
  public:
    // A's implementation needs Visitor's declaration
    void accept(Visitor *v) { v->visit(this) };
    void doSomething() { ... };
};

Это одна из причин, по которой вы хотите иметь объявление и реализацию в отдельных файлах. Есть много других причин, включая дифференциальное время компиляции.

Могу ли я спросить, почему вы хотите реализовать их все в одном файле?

Но:

В зависимости от того, чего вы пытаетесь достичь, вы можете захотеть обмануть. Но это будет боль поддерживать. Я никогда этого не сделаю, за исключением очень хорошей и необычной причины .

Например, я предполагаю, что что-то подобное должно работать:

class Doer {
  public:
    // Doer's implementation don't needs Visitor's declaration
    virtual void doSomething()=0;
};

class A;
class Visitor {
public:
    // Visitor's implementation needs Doer's declaration
    void visit(A *a){ ((Doer*)a)->doSomething(); }
};

class A: public Doer {
  public:
    // A's implementation needs Visitor's declaration
    void accept(Visitor *v) { v->visit(this) };
    void doSomething() override { ... };
};

Еще раз, если у вас есть выбор: не делайте этого . Предпочитаю разбивать ваш файл. Этот обходной путь, даже хорошо документированный, будет очень трудно поддерживать.

...