Как организовать занятия, содержащие смесь шаблонов и друзей? - PullRequest
0 голосов
/ 16 мая 2018

У меня есть два класса C ++, такие что:

  1. Первый класс содержит указатель на второй класс и имеет шаблонную функцию, которая вызывает открытый метод второго класса через указатель. Функция уже определена в объявлении класса, поскольку является шаблоном.
  2. Второй класс позволяет первому классу получить доступ к своим личным членам через механизм дружбы.

Учитывая это, у меня вопрос: как мне организовать объявления источников / заголовков / форвард для этой ситуации? Что бы я ни пытался, он просто не компилируется в объектный файл.

Одна последовательность такова:

class Class2;

class Class1
{
        Class2 * c2;
public:
        template<typename T> T DoSomething(T& X)
        {
                c2->Func();
                return X;
        };

        void FuncFromClass1();

};

class Class2
{
        int data;
public:
        Class2() : data(0) {};
        void Func();
        friend void Class1::FuncFromClass1();
};

void Class2::Func()
{
        int i;
}

void Class1::FuncFromClass1()
{
        int j;
        c2 = new Class2;
        c2->data = 1;
}

лает invalid use of incomplete type ‘class Class2’, потому что не распознает c2->Func();. Другой:

class Class1;

class Class2
{
        int data;
public:
        Class2() : data(0) {};
        void Func();
        friend void Class1::FuncFromClass1();
};

class Class1
{
        Class2 * c2;
public:
        template<typename T> T DoSomething(T& X)
        {
                c2->Func();
                return X;
        };

        void FuncFromClass1();

}; 

void Class2::Func()
{
        int i;
}

void Class1::FuncFromClass1()
{
        int j;
        c2 = new Class2;
        c2->data = 1;
}

Не распознает friend void Class1::FuncFromClass1();.

Компиляция пробуется как g++ -c -std=c++11 -Wall test.cpp.

Заметьте, я бы не стал делать Class1 целым другом, а хотел бы оставить только один из его методов в качестве друга для Class2, если это вообще возможно.

Кроме того, я не пробовал точно такой же пример в Visual Studio в Windows, но видел совершенно изоморфную ситуацию, подобную описанной (в рамках более крупного проекта), и, насколько я помню, от VS не было никаких жалоб. Это уникально для g ++?

1 Ответ

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

Переместите реализацию шаблона функции-члена, где известно определение Class2.

class Class2;

class Class1
{
   private:
      Class2 * c2;
   public:

      // Delcare, don't define
      template<typename T> T DoSomething(T& X);

      void FuncFromClass1();

};

class Class2
{
   private:
      int data;
   public:
      Class2() : data(0) {};
      void Func();
      friend void Class1::FuncFromClass1();
};

// Define
template<typename T>
T Class1::DoSomething(T& X)
{
   c2->Func();
   return X;
};

Обратите внимание, что предлагаемое решение является простым, если оба класса определены в одном файле .h.Если классы определены в отдельных файлах .h, все становится немного сложнее.Вам нужно убедиться, что файл .h, в котором определено Class1::DoSomething(), равен #include d в каждом файле .cpp, где вы хотите использовать Class1::DoSomething().

.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...