Перегруженное наследование оператора приведения (Visual C ++) - PullRequest
0 голосов
/ 25 марта 2012

Следующий код компилируется в XCode, но не в VS2008 / VS2010 (ошибка: неоднозначное преобразование, определенное пользователем). Если я использую функцию вместо оператора приведения, она соответствует без ошибок. Это ошибка VS?

#include <stdio.h>

class A
{

public:

    virtual operator int() const
    {
        return 1;
    }
};

class B : public virtual A
{

public:

    virtual operator int() const
    {
        return 2;
    }
};

class C : public virtual A, public virtual B
{

public:

};

int main()
{

    C c;

    int i = (int)c;

    printf("%d\n", i);
    return 0;
}

Ответы [ 2 ]

3 голосов
/ 04 августа 2012

Ошибка возникает из-за того, что компилятор обнаруживает, что может делать что-то по-разному, поскольку приведение неявно, компилятору необходимо выбрать «правильный путь».

Начиная с вашего случая: компилятор не может сделать что-то вроде

(int) c;

Он не знает как, но он может привести c к чему-то, что он знает, как привести к int, но это оставляет два варианта:

(int) A(c);
(int) B(c);

Оба одинаково действительны и очень разные! Нет способа узнать, что реализовать. На самом деле, вы можете даже столкнуться с проблемой, если у вас есть переменная b типа B, так как вы можете привести два пути:

(int) b;
(int) A(b);

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

  1. Сделайте приведение типов от B к A, C к B и C к A явным. Затем создайте функция приведения, которая сначала преобразует это в нужный вам класс, и затем приводит это к int. Это, хотя не будет работать с визуальным студия, которую вы используете, так что это не будет работать для вашего случая.

  2. Сделайте класс B защищенным, но, так как вы хотите, чтобы C был приведен как B, это не работает. Из-за проблемы при приведении B к int вы не можете просто сделать A защищенным.

  3. Определите операцию приведения в A, но сделайте так, чтобы она вызывала виртуальную функцию, которая B переопределение. Таким образом, есть только одна операция приведения, определенная в A, без двусмысленного случая.

Я думаю, что третий вариант - лучший в вашем случае, он будет выглядеть примерно так:

#include <stdio.h>

class A
{

protected:

    virtual int _int_cast() const
    {
       return 1;
    }

public:

    operator int() const
    {
        return this->_int_cast();
    }
};

class B : public virtual A
{

protected:

    virtual int _int_cast() const
    {
        return 2;
    }
};

class C : public virtual A, public virtual B
{

public:

};

int main()
{

    C c;

    int i = (int)c;

    printf("%d\n", i);
    return 0;
}

В основном: не переопределяйте перегруженные приведения из классов, которые вы наследуете, предположите, что он должен сначала преобразоваться в базовый класс. Также следите за перегруженными приведениями, которые очень похожи, например, вы можете преобразовать в int, а затем в const int или просто привести непосредственно к const int.

2 голосов
/ 25 марта 2012

Возможно, вы получаете предупреждение в xcode? Я не смог проверить код в xcode, но смог в VS2010 и получил одно предупреждение и одну ошибку.

Внимание:

main.cpp(30): warning C4250: 'C' : inherits 'B::B::operator int' via dominance main.cpp(19) : see declaration of 'B::operator int'

Ошибка:

main.cpp(37): error C2440: 'type cast' : cannot convert from 'C' to 'int'

Предупреждение может помочь объяснить ошибку в вашем случае. Предупреждение описано в http://msdn.microsoft.com/en-us/library/6b3sy7ae%28v=vs.80%29.aspx, который я предлагаю вам прочитать.

Что касается ошибки, ну, я не могу сказать на 100% уверенности, кроме как, возможно, наследство, вызывающее проблему. Если вы определили оператор int для c, он скомпилируется.

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