Как заставить компилятор выбирать не шаблонную версию метода для производных классов? - PullRequest
0 голосов
/ 15 августа 2011

Я пишу матричный класс (CMatrix) с такими производными классами, как трехмерный вектор (CVector) и матрица вращения (CRotMatrix).Мой объект CMatrix может быть умножен на другой объект на основе CMatrix или на любое числовое значение (скалярное).Этот код представляет суть проблемы, которую я получил:

template<class T> class CMatrix
{

public:

    template<class U> const CMatrix& operator=(const CMatrix<U> &inp){return (*this);}

    CMatrix& operator*(const CMatrix &inp) 
    {   
        cout<<"Multiplication by CMatrix"<<endl;
        return (*this);
    }

    template<class U> 
    CMatrix& operator*(const U &inp)
    {
        cout<<"Multiplication by a scalar."<<endl;
        return (*this);
    }

};

template<class T> class CVector: public CMatrix<T>{};
template<class T> class CRotMatrix: public CMatrix<T>{};

int main()
{
    CMatrix<int> foo1;
    CMatrix<int> foo2;
    CVector<int> dfoo1;
    CRotMatrix<int> dfoo2;

    foo1 = foo1*foo2;   //calls CMatrix method
    foo1 = foo1*5;      //calls scalar method
    foo1 = foo1*dfoo2;  //calls scalar method, shoud be CMatrix
    foo1 = dfoo2*dfoo1; //calss scalar method, shoud be CMatrix

    return 0;
}

Проблема в том, что компилятор предпочитает шаблонную версию оператора * ().Есть ли способ заставить компилятор выбрать правильный метод для производных классов CMatrix в этой ситуации?Если я отключу этот метод

CMatrix& operator*(const U &inp)

Компилятор делает это правильно, но класс теряет способность умножаться на скаляр.Я использую msvc10.Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 15 августа 2011

Причина в том, что оператор шаблона считается точным соответствием, а версия матрицы требует преобразования в родительскую ссылку.Таким образом, компилятор выбирает шаблон как лучшее соответствие.

Сначала подумайте, действительно ли вам нужны дочерние классы, которые вы создали, и предоставляют ли они соответствующие функции / переопределения.тогда я бы решил проблему, сделав одну или обе операции не оператором .Заставляя operator* делать оба вида умножения, вы нарушаете принцип наименьшего удивления, когда он делает две совершенно разные вещи в зависимости от контекста.Я бы предложил именованные методы для обоих, так что это очевидно, но в противном случае я бы предложил operator* быть математикой и функцией ScalarMultiply для выполнения одного скалярного типа.

1 голос
/ 15 августа 2011

Проблема в том, что компилятор предпочитает шаблонную версию оператора * ().Есть ли способ заставить компилятор выбрать правильный метод для производных классов CMatrix в этой ситуации?

Это потому, что вы сказали это.Ваш Multiplication by a scalar метод является более общим, чем ваш Multiplication by CMatrix метод.

Сделайте ваш метод "Умножение скалярным" тем, что в комментарии говорится:* Приложение
Ваш template<class U> CMatrix& operator*(const U &inp) настолько универсален, что соответствует всему .Умножается на std::istream: нет проблем.Он печатает Multiplication by a scalar. Вы хотите, чтобы ваше умножение на скаляр было ограничительным, а не универсальным для любого случайного типа.

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