перегрузка *, +, -'операторов для класса vector‹double›

Я пишу класс Line для создания числовых методов и хочу, чтобы эти операторы (*, +, -) сделали мой код более читабельным и понятным.

        #include <vector>

        using namespace std;

        typedef vector<double> Vector;

        class Line : public Vector
        {
        public:
            Line();
            ~Line();

            Line operator+(Line);
            Line operator-(Line);
            Line operator*(double);
        };


        Line Line::operator*(double alfa)
        {
            Line temp;
            int n = size();
            temp.resize(n);
            for (int i = 0; i < n; i++)
            {
                temp.at(i) = this->at(i)*alfa;
            }
            return temp;
        }

        Line Line::operator+(Line line)
        {
            int n = size();
            Line temp;
            temp.resize(n);
            for (int i = 0; i < n; i++)
            {
                temp.at(i) = this->at(i) + line[i];
            }
            return temp;
        }

        Line Line::operator-(Line line)
        {
            int n = size();
            Line temp;
            temp.resize(n);
            for (int i = 0; i < n; i++)
            {
                temp.at(i) = this->at(i) - line[i];
            }
            return temp;
        }


        int main()
        {
            return 0;
        }

Можно ли перегрузить такие операторы из класса Vector? я должен просто делать функции (или методы) вместо операторов? любые другие предложения?

ps1: я использую Visual Studio 11 в качестве компилятора.

ps2: я не запускал проект как «проект win32», это консольное приложение.

Я получаю следующие ошибки:

Error   1   error LNK2019: unresolved external symbol "public: __thiscall Line::Line(void)" (??0Line@@QAE@XZ) referenced in function "public: class Line __thiscall Line::operator*(double)" (??DLine@@QAE?AV0@N@Z) C:\Users\Lucas\Documents\Visual Studio 11\Projects\test\test\test.obj   test


Error   2   error LNK2019: unresolved external symbol "public: __thiscall Line::~Line(void)" (??1Line@@QAE@XZ) referenced in function "public: class Line __thiscall Line::operator*(double)" (??DLine@@QAE?AV0@N@Z)    C:\Users\Lucas\Documents\Visual Studio 11\Projects\test\test\test.obj   test

person Lucas Da Rocha Souza    schedule 19.01.2013    source источник
comment
Наследовать от std::vector — очень плохая идея. Кроме того, вы никогда не определяли свой ctor/dtor.   -  person chris    schedule 20.01.2013
comment
Должен ли я тогда просто создавать функции, или у вас есть другая идея?   -  person Lucas Da Rocha Souza    schedule 20.01.2013
comment
Обычно лучше просто придерживаться состава для стандартных контейнеров.   -  person chris    schedule 20.01.2013
comment
С операторами все в порядке, но используйте агрегацию.   -  person lethal-guitar    schedule 20.01.2013
comment
Используйте что-то вроде Boost.uBLAS, в котором все это уже есть, не изобретайте велосипед.   -  person Philipp    schedule 20.01.2013
comment
Вы смотрели en.cppreference.com/w/cpp/header/valarray ?   -  person rici    schedule 20.01.2013


Ответы (4)


Вы должны перегрузить операторы в глобальной области видимости:

vector<double> operator*(const vector<double>& v, double alfa)
{
    ...
}

vector<double> operator+(const vector<double>& v1, const vector<double>& v2)
{
    ...
}

vector<double> operator-(const vector<double>& v1, const vector<double>& v2)
{
    ...
}

Что касается ошибок компоновщика, похоже, вы не реализовали конструктор и деструктор Line.

person user1610015    schedule 20.01.2013
comment
По моему непрошенному мнению, не лучшая идея перегружать операторы, которые принимают аргументы только чужих типов, особенно в глобальной области видимости, где какая-то другая глупая библиотека могла сделать то же самое. - person Benjamin Lindley; 20.01.2013
comment
@BenjaminLindley Да, именно поэтому это прямо запрещено стандартом - шаблоны должны быть сначала параметризованы с помощью типов пользователей. - person StaceyGirl; 26.03.2020

Вы никогда не должны наследовать от std-классов, которые не предназначены для наследования. Наследование от классов, у которых нет виртуального деструктора, очень опасно.

Я предлагаю вам использовать агрегацию: сделайте так, чтобы ваш класс Line содержал член типа vector, например, с именем myVector_, и реализовывал нужные операторы таким образом, чтобы они использовали эту переменную-член.

Таким образом, вы заменяете все вызовы size() на myVector.size() и т. д.:

Line Line::operator*(double alfa)
{
    Vector temp;
    int n = myVector_.size();
    temp.resize(n);
    for (int i = 0; i < n; i++)
    {
        temp.at(i) = myVector_.at(i)*alfa;
    }
    return temp;
}
person lethal-guitar    schedule 19.01.2013
comment
Я пытался это сделать, но основная проблема связана с оператором [], я не мог заставить его вернуть указатель. например: A[i][j] = что-то.... Не сработало, мне пришлось бы ввести что-то вроде: A[i].v.at(j) = что-то... Чтобы это сработало. ты для ctor/dtor я не знал об этом. - person Lucas Da Rocha Souza; 20.01.2013
comment
Что именно вы имеете в виду? return myVector_[i]; не должно быть проблем, если тип возвращаемого значения функции правильный - person lethal-guitar; 20.01.2013
comment
Или вы имеете в виду, что хотите получить доступ к внутреннему массиву? Просто используйте &myVector_[0] или myVector_.data(), если вы используете C++ 11 - person lethal-guitar; 20.01.2013

Ошибка компоновщика сообщает вам, что в вашем коде отсутствуют определения двух объявленных вами функций-членов — конструктора и деструктора:

Line::Line() {
    // Code of the constructor goes here
}

Line::~Line() {
    // Code of the destructor goes here
}
person Sergey Kalinichenko    schedule 19.01.2013

Конечно, правильно иметь объект Vector ВНУТРИ строки, а не «наследовать» от Vector? Как правило, наследование от контейнеров std:: - это не очень хорошие данные... Я почти уверен, что «Линия» на самом деле не является вектором, это «имеет» вектор. [Правило для «когда вы наследуете»: «X есть Y», когда вы создаете составной объект, когда «X имеет Y», поэтому внутри X есть Y.]

Вам нужно будет объявить свой конструктор и деструктор, чтобы избавиться от ошибки связывания.

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

person Mats Petersson    schedule 19.01.2013