Почему только одно неявное преобразование позволяет преобразовать параметры в функцию в C ++? - PullRequest
1 голос
/ 26 июня 2010

Это работает:

#include<cstdio>

class A{
public:
    A(int a):var(a){}
    int var;
};

int f(A obj) {
    return obj.var;
}

int main() {
    std::cout<<f(23);  // output: 23
    return 0;
}

пока это не так:

#include<cstdio>

class A{
public:
    A(int a, int b):var1(a), var2(b){}
    int var1, var2;
};

int f(A obj) {
    return (obj.var1 + obj.var2);
}

int main() {

    cout<<f(22, 23); // error: conversion from 'int' to 
                     // non-scalar type 'A' requested
    return 0;
}

Второй фрагмент кода не работает, но я не могу найти достаточно вескую причину, почему он не работает. Для меня код выглядит слишком странным, чтобы работать.

Но какова действительная причина того, что в подобных ситуациях допускается только одно неявное преобразование? Это языковая особенность "это как это только это"?

Ответы [ 3 ]

8 голосов
/ 26 июня 2010

Прямой ответ: грамматика C ++ не объединяет аргументы функции в агрегаты ни при каких обстоятельствах.Ни в коем случае вызов f(a, b) не будет рассматриваться как вызов f(c), где c - это значение, построенное из некоторой комбинации a и b.Это просто не так, как работает язык.Каждый аргумент всегда обрабатывается отдельно для перегрузки, неявного преобразования и всех других целей.

Что касается обоснования, если то, о чем вы спрашиваете, разрешено, как вы ожидаете, что эта ситуация будет разрешена:*

class A {
  public:
    A(int a) : v1(a) {}
  private:
    int v1;
};

class B {
  public:
    B(int a, int b) : v1(a), v2(b) {}
  private:
    int v1;
    int v2;
};

class C {
  public:
    C(int a, int b, int c) : v1(a), v2(b), v3(c) {}
  private:
    int v1;
    int v2;
    int v3;
};

void f(A obj1, A obj2) { /* ... */ }

void f(B obj) { /* ... */ }

void g(A obj1, B obj2) { /* ... */ }

void g(B obj1, int i) { /* ... */ }

void g(C obj) { /* ... */ }

int main() {
   f(22, 23); // Call f(A,A) or f(B)? 
   g(22, 23, 24); // Call g(A,B) or g(B, int), or g(C)? 
   return 0;
}
1 голос
/ 26 июня 2010

Только конструкторы, которые могут быть вызваны с одним аргументом, определяют неявные преобразования, поэтому во втором примере неявные преобразования невозможны, поскольку ни один конструктор из A не принимает один аргумент.

1 голос
/ 26 июня 2010

Вы смотрите на второй пример, как будто (22, 23) где кортеж (то есть одна переменная, которая является парой), когда их нет.Функция f принимает только одну переменную.Когда вы пытаетесь передать ему две переменные, которые потерпят неудачу.

Причина, по которой первая работает, заключается в том, что компилятор может приводить от int к A. Однако вы не можете привести две переменные к одной переменнойC ++ не позволяет этого.

...