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

Test.cpp:6:7 ошибка: вызов перегруженного 'Mat4()' неоднозначен

В моем тестовом коде я хочу

Mat4 I; // to result in a call to SetIdentity() via the default constructor
I.Print( "I = " ); // should print the Identity Matrix for a 4x4

Соответствующий код Mat4.h:

class Mat4{
protected:
    float   m[4][4];

public:
    // ** 3A: **
Mat4( );
Mat4( float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0 );

И мой код Mat4.cpp:

Mat4::Mat4( ){
SetIdentity( );
}

Mat4::Mat4( float a, float b, float c, float d, float e, float f, float g, float h,   float i, float j, float k, float l, float n, float o, float p, float q){
m[0][0] = a;
m[0][1] = b;
m[0][2] = c;
m[0][3] = d;
m[1][0] = e;
m[1][1] = f;
m[1][2] = g;
m[1][3] = h;
m[2][0] = i;
m[2][1] = j;
m[2][2] = k;
m[2][3] = l;
m[3][0] = n;
m[3][1] = o;
m[3][2] = p;
m[3][3] = q;
}

Пример использования конструктора не по умолчанию:

Mat4
Mat4::operator*( Mat4& that ){
// "this" is a pointer to this class's mat4  (this->name)
// "that" is a reference to the other matrix (that.name)

Mat4 result(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
int i, j, k;
for(i = 0; i < 4; i++){
    for(j = 0; j < 4; j++){
        for(k = 0; k < 4; k++){
            result.m[i][j] += (float)(this->m[i][k]*that.m[k][j]);
        }
    }
}
return result;
}

Спасибо за помощь!

0
Borne2Run_When_SegFault 13 Окт 2014 в 07:33
Как компилятор должен узнать, хотите ли вы вызвать Mat4 без аргументов или со всеми аргументами по умолчанию? Вам нужно либо удалить конструктор по умолчанию (и, следовательно, всегда вызывать Mat4 со всеми нулями), либо сделать так, чтобы первый аргумент конструктора не по умолчанию не имел значения по умолчанию (например: Mat4(float, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0);) (примечание первый float не имеет аргумента по умолчанию)
 – 
Steve Lorimer
13 Окт 2014 в 07:36
Второй вариант сработал и очень помог, спасибо! Я думал, что компилятор будет знать, были ли заданы параметры «Mat4» или нет, удалив затем значение, отличное от значения по умолчанию, исправило мою проблему.
 – 
Borne2Run_When_SegFault
13 Окт 2014 в 07:43
1
Лоример: В терминологии C++ оба этих конструктора являются конструкторами по умолчанию. Собственно, это и вызвало двусмысленность в первую очередь: OP объявил класс с двумя конструкторами по умолчанию, и компилятор не знает, какой из них использовать. Ваш второй вариант предлагает превратить один конструктор по умолчанию в нестандартный.
 – 
AnT
13 Окт 2014 в 07:46

2 ответа

Компилятор вообще не различает конструктор без параметров Mat4( ); из конструктора со всеми параметрами по умолчанию Mat4(float=0,float=0... ).
В том, как вы их определили, неясно, какой конструктор необходимо вызывать при вызове Mat4().

Наивные решения:
1. вы можете добавить фиктивный параметр к вашему Mat4(), например, Mat4 (bool b), чтобы разрешить двусмысленность или
2. сделать первый параметр в вашем конструкторе со многими параметрами не по умолчанию

Все эти решения связаны с проблемой, но не с причиной этой проблемы.
Причиной проблемы является ошибка в разработке метода.

Обновить (предлагаемое решение – изменить дизайн методов):
такая ошибка показывает, что дизайн методов вашего класса не соответствует требованиям.
поэтому, как предложил @sth, используйте один конструктор вместо неоднозначного 2.
все необходимые сценарии могут быть обработаны в теле этого конструктора, поэтому мы получаем:

Matrix(float[] arr = 0, int sizeOfArray = 0)
{
  if (arr == 0)
    // use scenario which you used for Matrix()
  else // use scenario which you used for Matrix(float,float...)
}

второй вариант, вместо размещения проверки в теле конструктора и выбора варианта на основе условия можно реализовать выбор на основе разрешения перегрузки:
когда вам нужно 2 конструктора:

Matrix(float[] arr, int sizeOfArray)
Matrix()
1
spin_eight 13 Окт 2014 в 16:32
3. Возможно, вам не нужны два отдельных конструктора, может быть достаточно одного со всеми аргументами по умолчанию.
 – 
sth
13 Окт 2014 в 08:04
Конечно, достаточно, еще и сигнатуру надо поменять, вместо float,float,float... Я бы предложил (float[], int size)
 – 
spin_eight
13 Окт 2014 в 15:32
Почему вы это предлагаете?
 – 
Oktalist
13 Окт 2014 в 16:35
Потому что это более общее
 – 
spin_eight
13 Окт 2014 в 17:02
std::initializer_list или пара итераторов были бы более общими и не входили бы в образ мышления программиста C.
 – 
Oktalist
13 Окт 2014 в 18:30

Компилятор не знает, является ли "Mat4()" или "Mat4( float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0, float=0 , float=0, float=0, float=0, float=0, float=0, float=0, float=0 )" при определении "Mat4 I"

0
gotojyh 13 Окт 2014 в 08:28