Pergunta

Todos nós sabemos que você pode sobrecarregar uma função de acordo com os parâmetros:

int mul(int i, int j) { return i*j; }
std::string mul(char c, int n) { return std::string(n, c); } 

Você pode sobrecarregar uma função de acordo com o valor de retorno? Definir uma função que retorna coisas diferentes de acordo com a forma como o valor de retorno é usado:

int n = mul(6, 3); // n = 18
std::string s = mul(6, 3); // s = "666"
// Note that both invocations take the exact same parameters (same types)

Você pode assumir o primeiro parâmetro é entre 0-9, não há necessidade de verificar a entrada ou ter qualquer tratamento de erros.

Foi útil?

Solução

class mul
{
public:
    mul(int p1, int p2)
    {
        param1 = p1;
        param2 = p2;
    }
    operator int ()
    {
        return param1 * param2;
    }

    operator std::string ()
    {
        return std::string(param2, param1 + '0');
    }

private:
    int param1;
    int param2;
};

Não que eu usaria isso.

Outras dicas

Você tem que dizer ao compilador qual versão usar. Em C ++, você pode fazê-lo de três maneiras.

Explicitamente diferenciar as chamadas digitando

Você um pouco enganado, porque você enviou um inteiro para uma espera função para um char, e erroneamente enviado o número seis, quando o valor de char de '6' não é 6, mas 54 (em ASCII):

std::string mul(char c, int n) { return std::string(n, c); }

std::string s = mul(6, 3); // s = "666"

A solução certa seria, é claro,

std::string s = mul(static_cast<char>(54), 3); // s = "666"

Este foi vale a pena mencionar, eu acho que, mesmo se você não quer a solução.

Explicitamente diferenciar as chamadas de manequim ponteiro

Você pode adicionar um parâmetro fictício para cada função, forçando assim o compilador para escolher as funções certas. A maneira mais fácil é enviar um ponteiro NULL fictício do tipo desejado para o retorno:

int mul(int *, int i, int j) { return i*j; }
std::string mul(std::string *, char c, int n) { return std::string(n, c); }

Que pode ser usado com o código:

int n = mul((int *) NULL, 6, 3); // n = 18
std::string s = mul((std::string *) NULL, 54, 3); // s = "666"

Explicitamente diferenciar as chamadas por templates o valor de retorno

Com esta solução, criamos uma função "dummy" com o código que não irá compilar se instanciado:

template<typename T>
T mul(int i, int j)
{
   // If you get a compile error, it's because you did not use
   // one of the authorized template specializations
   const int k = 25 ; k = 36 ;
}

Você vai notar esta função não será compilado, que é uma coisa boa porque queremos apenas para usar algumas funções limitadas através de especialização de modelo:

template<>
int mul<int>(int i, int j)
{
   return i * j ;
}

template<>
std::string mul<std::string>(int i, int j)
{
   return std::string(j, static_cast<char>(i)) ;
}

Assim, o código a seguir irá compilar:

int n = mul<int>(6, 3); // n = 18
std::string s = mul<std::string>(54, 3); // s = "666"

Mas este não vai:

short n2 = mul<short>(6, 3); // error: assignment of read-only variable ‘k’

Explicitamente diferenciar as chamadas por templates o valor de retorno, 2

Ei, você me enganou, também!

Certo, eu uso os mesmos parâmetros para as duas funções "sobrecarregados". Mas você fez começar a fazer batota (veja acima) ...

^ _ ^

Mais a sério, se você precisa ter diferentes parâmetros, então você vai escrever mais código, e depois ter de usar explicitamente o direito tipos ao chamar as funções a ambiguidades evitar:

// For "int, int" calls
template<typename T>
T mul(int i, int j)
{
   // If you get a compile error, it's because you did not use
   // one of the authorized template specializations
   const int k = 25 ; k = 36 ;
}

template<>
int mul<int>(int i, int j)
{
   return i * j ;
}

// For "char, int" calls
template<typename T>
T mul(char i, int j)
{
   // If you get a compile error, it's because you did not use
   // one of the authorized template specializations
   const int k = 25 ; k = 36 ;
}

template<>
std::string mul<std::string>(char i, int j)
{
   return std::string(j, (char) i) ;
}

E este código seria usado como tal:

int n = mul<int>(6, 3); // n = 18
std::string s = mul<std::string>('6', 3); // s = "666"

E a seguinte linha:

short n2 = mul<short>(6, 3); // n = 18

Será que ainda não compilar.

Conclusão

Eu amo C ++ ...

: - p

Se você queria fazer mul ser uma função real em vez de uma classe, você pode simplesmente usar uma classe intermediária:

class StringOrInt
{
public:
    StringOrInt(int p1, int p2)
    {
        param1 = p1;
        param2 = p2;
    }
    operator int ()
    {
        return param1 * param2;
    }

    operator std::string ()
    {
        return std::string(param2, param1 + '0');
    }

private:
    int param1;
    int param2;
};

StringOrInt mul(int p1, int p2)
{
    return StringOrInt(p1, p2);
}

Isto permite-lhe fazer coisas como passar mul como uma função em algoritmos std:

int main(int argc, char* argv[])
{
    vector<int> x;
    x.push_back(3);
    x.push_back(4);
    x.push_back(5);
    x.push_back(6);

    vector<int> intDest(x.size());
    transform(x.begin(), x.end(), intDest.begin(), bind1st(ptr_fun(&mul), 5));
    // print 15 20 25 30
    for (vector<int>::const_iterator i = intDest.begin(); i != intDest.end(); ++i)
        cout << *i << " ";
    cout << endl;

    vector<string> stringDest(x.size());
    transform(x.begin(), x.end(), stringDest.begin(), bind1st(ptr_fun(&mul), 5));
    // print 555 5555 55555 555555
    for (vector<string>::const_iterator i = stringDest.begin(); i != stringDest.end(); ++i)
        cout << *i << " ";
    cout << endl;

    return 0;
}

Não.

Você não pode sobrecarregar pelo valor de retorno porque o chamador pode fazer nada (ou nada) com ele. Considere o seguinte:

mul(1, 2);

O valor de retorno é apenas jogado fora, então não há nenhuma maneira que poderia escolher uma sobrecarga com base no valor de retorno sozinho.

Use conversão implícita em uma no meio da classe.

class BadIdea
{
  public:
    operator string() { return "silly"; }
    operator int() { return 15; }
};

BadIdea mul(int, int)

Você começa a idéia, péssima idéia embora.

Let Mul ser uma classe, mul (x, y) seu construtor, e sobrecarregar alguns operadores de conversão.

Você não pode sobrecarregar uma função com base no valor de retorno somente.

No entanto, enquanto estritamente falando, isso não é uma função sobrecarregada, você poderia retornar de sua função como resultado uma instância de uma classe que sobrecarrega os operadores de conversão.

Eu presumo que você poderia tê-lo retornar algum tipo estranho Foo que apenas captura os parâmetros e, em seguida, Foo tem um int implícita operador e corda operador, e que seria "trabalho", embora não seria realmente sobrecarga, em vez de uma implícita conversão truque.

Hmmm, o artigo do projeto seguinte código parece estar a fazer o que você é depois de. Deve ser mágico;)

curta e simples, a resposta é NÃO. Em C ++, os requisitos são:

1: nome de funções deve ser o mesmo
2: conjunto de argumentos devem diferir
* O tipo de retorno pode ser igual ou diferente

//This is not valid
    int foo();
    float foo();

    typedef int Int;

    int foo(int j);
    int foo(Int j);

//Valid:
   int foo(int j);
   char* foo(char * s);
   int foo(int j, int k);
   float foo(int j, float k);
   float foo(float j, float k);

Tanto quanto eu sei, você não pode (grande pena, embora ...). Como solução alternativa, você pode definir um parâmetro 'out' em vez disso, e sobrecarga que um.

Não em C ++. O que você deseja obter no exemplo acima seria o valor retornado que é um elenco int em algo string pode entender, provavelmente um char. Qual seria ASCII 18 ou "controle do dispositivo 2".

Você pode usar a solução functor acima. C ++ não suporta esta para as funções, exceto const. Você pode sobrecarregar com base em const.

Você pode usar um modelo, mas então você tem que especificar o parâmetro do modelo quando você faz a chamada.

Coloque-o em um espaço diferente? Isso seria como eu iria fazê-lo. Não estritamente uma sobrecarga, em vez de apenas ter dois métodos com o mesmo nome, mas um escopo diferente (operador de resolução, portanto, a :: escopo).

Assim stringnamespace :: mul e intnamespace :: Mul. Talvez a sua não realmente o que você está pedindo, mas parece que a única maneira de fazê-lo.

Você poderia fazer algo assim

template<typename T>
T mul(int i,int j){
    return i * j;
}

template<>
std::string mul(int i,int j){
    return std::string(j,i);
}

E, em seguida, chamá-lo assim:

int x = mul<int>(2,3);
std::string s = mul<std::string>(2,3);

Não há nenhuma maneira de sobrecarga no valor de retorno.

OK você gênios;.) Este é como fazê-lo como um profissional


class mul
{
 int m_i,m_j;
public:
 mull(int i,int j):m_i(i),m_j(j){}
 template
 operator R() 
 {
  return (R)m_i * m_j;
 }
};

utilização como


double d = mul(1,2);
long l = mul(1,2);

não estúpido <>

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top