У меня есть два класса, которые должны ссылаться друг на друга в одном файле cpp, но первый не распознает объекты второго типа - PullRequest
0 голосов
/ 16 февраля 2020

Компилятор выдаёт мне: "переменная имеет тип не завершён вращением2d"

class translation2d
{
    public:
       double x;
       double y;

        translation2d()
        {
            x=0;
            y=0;
        }
    translation2d rotateBy(rotation2d rotation) //issue here
    {
        translation2d copy=*this;
        copy=translation2d(x*rotation.cosM()-y*rotation.sinM(), x*rotation.sinM() + y*rotation.cosM());
        return copy;
    }
};
double kEpsilon = 0.000000009;

class translation2d;
class rotation2d
{

    public:
       double cosAngle;
       double sinAngle;

    public:
        rotation2d() 
        {
            cosAngle=1;
            sinAngle=0;
        }

        rotation2d(translation2d& direction, bool norm)
        {
            cosAngle=direction.x;
            sinAngle=direction.y;
            if(norm)
                normalize();
        }

    double cosM()
    {
        return cosAngle;
    }
    double sinM()
    {
        return sinAngle;
    }
    double tanM()
    {
        if(abs(cosAngle)<kEpsilon)
        {
            if(sinAngle>=0.0)
                return std::numeric_limits<double>::infinity();
            else
                return -1*std::numeric_limits<double>::infinity();
        }
        return sinAngle/cosAngle;
    }
}

1 Ответ

0 голосов
/ 16 февраля 2020

Чтобы разрешить циклические зависимости в C ++, для * изобретены *1001* форвардные объявления.

Каким-то образом OP попытался, но неправильно.

Так, если

  • class translation2d необходимо class rotation2d

и

  • class rotation2d необходимо class translation2d

второй должен быть объявлен вперед перед первым.

struct rotation2d; // forward declaration -> incomplete type

struct translation2d {
  void doSomethingWith(rotation2d rot);
};

struct rotation2d {
  void doSomethingWith(translation2d trans);
};

Демонстрация в Compiler Explorer

Предварительное объявление делает неполного типа . Неполные типы ограничены относительно того, что можно сделать с ними.

Ни размер, ни содержимое неполного типа не известны. Следовательно, компилятор запрещает все, где это необходимо, например,

  • выделение памяти (т.е. создание из нее переменной или члена-переменной)
  • доступ к содержимому (т.е. чтение / запись переменные-члены или вызов функций-членов).

Допускается использование неполных типов для

  • указателей и ссылок (с любой квалификацией)
  • параметров объявления функций.

Я должен признать, что не знал о последнем, но обнаружил: SO: неполные типы в качестве параметров функции и возвращаемых значений для моего освещения.

Обратите внимание, что параметры функции декларации могут быть неполными, но не параметры функции определения . Следовательно, вторая часть исправления состоит в том, чтобы сделать функции non- встроенными, если в них требуются неполные типы.

struct rotation2d; // forward declaration -> incomplete type

struct translation2d {
  void doSomethingWith(rotation2d rot);
};

struct rotation2d {
  void doSomethingWith(translation2d trans)
  {
    trans; // will be processed somehow
  }
};

// now both types are complete

void translation2d::doSomethingWith(rotation2d rot)
{
  rot; // will be processed somehow
}

Демонстрация в Compiler Explorer


Фиксированный и завершенный пример кода OP:

#include <iostream>
#include <limits>
#include <cmath>

class rotation2d; // forward declaration

class translation2d
{
    public:
       double x;
       double y;

        translation2d()
        {
            x=0;
            y=0;
        }
        translation2d(double x, double y): x(x), y(y) { }

    translation2d rotateBy(rotation2d rotation); //issue here fixed
};
double kEpsilon = 0.000000009;

class rotation2d
{

    public:
       double cosAngle;
       double sinAngle;

    public:
        rotation2d() 
        {
            cosAngle=1;
            sinAngle=0;
        }

        rotation2d(const translation2d& direction, bool norm)
        {
            cosAngle=direction.x;
            sinAngle=direction.y;
            if(norm)
                normalize();
        }

    double cosM()
    {
        return cosAngle;
    }
    double sinM()
    {
        return sinAngle;
    }
    double tanM()
    {
        if(abs(cosAngle)<kEpsilon)
        {
            if(sinAngle>=0.0)
                return std::numeric_limits<double>::infinity();
            else
                return -1*std::numeric_limits<double>::infinity();
        }
        return sinAngle/cosAngle;
    }

    void normalize()
    {
        const double len = std::sqrt(cosAngle * cosAngle + sinAngle * sinAngle);
        cosAngle /= len; sinAngle /= len;
    }
};

// both types complete now -> circular dependency resolved

translation2d translation2d::rotateBy(rotation2d rotation)
{
    translation2d copy=*this;
    copy=translation2d(x*rotation.cosM()-y*rotation.sinM(), x*rotation.sinM() + y*rotation.cosM());
    return copy;
}

int main()
{
    translation2d t(1.0, 2.0);
    rotation2d r(translation2d(0.0, 1.0), false);
    translation2d tR = t.rotateBy(r);
    std::cout << "tR: (" << tR.x << ", " << tR.y << ")\n";
}

Вывод:

tR: (-2, 1)

Live Demo на колиру

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