C ++ принимает неправильный тип возврата - PullRequest
0 голосов
/ 12 июля 2020

У меня есть следующий код, который, по моему мнению, не должен компилироваться: (В class Vector ( не std::vector, а Vector, который я определил сам)):

Vector operator*(double factor)
{
  // some element-wise multiplication here
  return factor;
}

Я определяю этот оператор для возврата Vector, но внутри метода я возвращаю double.

У меня также есть not операторы неявного преобразования внутри класса.

Я бы подумал, что это явно недействительно, но g cc с радостью компилирует это без каких-либо жалоб.

Мой первый рефлекс - отправить отчет о дефекте на g cc, но я подумал, что спрошу здесь раньше ..

Мне здесь не хватает чего-то, что могло бы объяснить, почему этот код считается допустимым компилятором?

(Если это актуально, стандарт c ++ установлен на c ++ 17)

Дополнительная информация о классе Vector: (а именно, я включаю все объявленные конструкторы и операторы, как и другие, названные функции не должны способствовать возникновению этой проблемы):

class Vector {
public:
  Vector(std::vector<double> values);
  Vector(size_t dimension, double value);
  Vector(size_t dimension);

  void operator*=(double factor);
  void operator*=(Vector const& factor);

  friend Vector operator-(Vector const& a, Vector const& b);
  friend Vector operator+(Vector const& a, Vector const& b);
  friend Vector operator*(Vector const& a, Vector const& b);

  Vector operator*(double factor);
  double& operator[](size_t i);

  friend std::ostream& operator<<(std::ostream& stream, Vector const& v);
}

1 Ответ

1 голос
/ 14 июля 2020

На основе полученных комментариев:

Неявные операторы преобразования - не единственный способ, с помощью которого возвращаемое значение, изначально имеющее неправильный тип, может «стать» типом, необходимым для функции - подпись. Конструктор

Vector(size_t dimension);

Принимает в качестве аргумента одно числовое значение, которое само по себе не double, а long unsigned int, но double может быть преобразовано в это.

Итак, происходит следующее: сначала double factor преобразуется в long unsigned int, а затем происходит неявное построение Vector с использованием конструктора Vector(size_t dimension);. Затем возвращается объект, который является результатом этой конструкции.

Следовательно, это действительный код в том смысле, что он не нарушает языковые правила, компилятор определенно не делает здесь ничего плохого.

Если такое поведение не требуется, соответствующий конструктор должен быть помечен explicit следующим образом:

explicit Vector(size_t dimension);

Если было несколько конструкторов, принимающих один аргумент типа, в который можно преобразовать double , или чьи первые аргументы удовлетворяют этому требованию, а все остальные аргументы являются необязательными, например:

Vector(int a, char b = 'c');

они также должны быть помечены explicit, но в этом случае вполне вероятно, что компилятор пожаловаться, потому что он не может определить, какой конструктор вызвать.

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