C ++: чисто виртуальный оператор присваивания - PullRequest
5 голосов
/ 21 сентября 2010

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

в настоящее время у меня есть только следующее объяснение http://support.microsoft.com/kb/130486, в котором говорится, что поведение является заданным, поскольку обычные правила наследования не применяются .

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

edit: добавлен мой упрощенный код , из которых произошла ошибка:

class __declspec(dllexport) BaseClass {
public:
    int memberA;
    virtual BaseClass& operator=(const BaseClass& rhs) = 0;
};

class __declspec(dllexport) DerivedClass : public BaseClass {
public:
    int memberB;
    DerivedClass():memberB(0) {}
    virtual BaseClass& operator=(const BaseClass& rhs) {
        this->memberA = rhs.memberA;
        this->memberB = 1;
        return *this;
    }
};

int main(void)
{
    DerivedClass d1;
    DerivedClass d2;

    BaseClass* bd1 = &d1;
    BaseClass* bd2 = &d2;

    *bd1 = *bd2;
}

код будет компилироваться без ошибок без __declspec(dllexport) и / или без чистого виртуального оператора = объявление в базовом классе.

без __declspec(dllexport) после присвоения *bd1 = *bd2;, d1 :: memberB равно 1, но с __declspec(dllexport) d1 :: memberB остается без изменений

с __declspec(dllexport) и без чисто виртуального объявления, после присвоения *bd1 = *bd2; d1 :: memberB остается без изменений

Ответы [ 3 ]

7 голосов
/ 21 сентября 2010

Из раздела 12.8 стандарта:

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

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

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

7 голосов
/ 21 сентября 2010

operator = не наследуется.Ваш код не имеет смысла в C ++, поэтому компиляторы могут выдавать любую ошибку, какую захотят.

Из статьи базы знаний, на которую вы указали: http://support.microsoft.com/kb/130486

Так как operator = isне наследуется, любое объявление оператора = в базовом классе не используется и не нужно.Не объявляйте оператор = в базовом классе.

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

2 голосов
/ 21 сентября 2010

В примере кода:

class A
{
public :
   // To workaround LNK2001, comment the following line.
   virtual const A& operator=( const A& f ) = 0;
};

class B : public A
{
public :
   const A& operator=( const A& g ) {return g;}
};

B aB1, aB2;

int /*void*/ main( void )
{
   aB2 = aB1;
}

строка aB2 = aB1 не вызывает const A& B::operator=(const A&), а вместо этого вызывает автоматически предоставленный B& operator=(const B&);, который, в свою очередь, использует оператор присваивания для назначения базовой частикласса.Но когда дело доходит до ссылок, оказывается, что это никогда не было реализовано.

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