Подклассы, перегрузка оператора присваивания? - PullRequest
6 голосов
/ 07 сентября 2011

Если у меня есть приведенные ниже классы:

class TestA
{
    public:
        const TestA &operator=(const int A){return *this;}
};

class TestB : public TestA
{
    public:
        //Inheritance?
};

Вопрос предполагает, что и класс TestA, и класс TestB имеют одинаковое содержимое в терминах переменных: является ли оператор присваивания (или любой другой оператор) наследуемым?

Действительно ли следующее?

class TestB : public TestA
{
    public:
        using TestA::operator=;
        //Inheritance?
};

Если он действителен, будет ли это иметь значение?

Ответы [ 4 ]

3 голосов
/ 07 сентября 2011

Пример кода вопроса, когда я пишу это:

class TestA
{
    public:
        const TestA &operator=(const int A){return *this;}
};

class TestB : public TestA
{
    public:
        //Inheritance?
};

Q1: «Является ли оператор присваивания (или любой другой оператор) унаследованным?»

Да, конечно.Единственными функциями-членами, которые не наследуются в C ++ 98, являются конструкторы.Однако реализации базового класса по умолчанию скрыты автоматически сгенерированным оператором copy assignment .Пример:

#include <iostream>
using namespace std;

class TestA
{
    public:
        TestA const& operator=( int const )
        {
            cout << "TestA = int" << endl;
            return *this;
        }
};

class TestB : public TestA
{
    public:
        // Automatically generated copy assignment operator.
};

int main()
{
    TestB   o;

    cout << "Calling automatically generated copy assignment:" << endl;
    cout << "(should be nothing here ->) ";  o = TestB();
    cout << endl;
    cout << endl;

    cout << "Calling base class assignment operator:" << endl;
    // o = 42;     // won't compile, because it's hidden.
    cout << "(should be output here ->) ";  o.TestA::operator=( 42 );   // OK.
    cout << endl;
}

Учитывая все ответы, которые до сих пор путали скрытие и наследование, и просто прояснить терминологию здесь, N3290 (которая идентична стандарту C ++ 11), говорит это:

N3290 §10 / 2:
«Унаследованные члены могут упоминаться в выражениях так же, как и другие члены производного класса, если только их имена не являются скрытыми илинеоднозначный "

В приведенном выше примере код TestA::operator= скрыт, но см. ответ на вопрос Q3.

Q2: Допустимо ли следующее?

Этот вопросотносится к использованию using в производном классе, например

class TestB : public TestA
{
    public:
        using TestA::operator=;
        //Inheritance?
};

Да, это действительно.

Это не будет допустимо в C ++ 98 для конструктора, потому что конструкторыне наследуются.

Q3: Если оно действительно, изменится ли оно?

Да, это делает оператор (ы) назначения базового класса напрямую доступным в производном классе.

Например, вы можете удалить комментирование на экзаменеСм. выше,

// o = 42;     // won't compile, because it's hidden.

, и он все равно будет компилироваться,

o = 42;        // compiles fine with "using".

Приветствия & hth.,

3 голосов
/ 07 сентября 2011

Операторы присваивания скрыты по производному классу по умолчанию (поскольку компилятор всегда генерирует T& operator = () для любого class T, если не указано). Что делает унаследованный operator = непригодным для использования.

Да при указании их с ключевым словом using; они становятся годными к употреблению . Демо . Так что ваш фрагмент кода имеет смысл.

public: using TestA::operator=;
2 голосов
/ 07 сентября 2011

Я нашел ответ по стандарту C ++ 11:

12.8 Копирование и перемещение объектов класса

Поскольку оператор назначения копирования / перемещения неявно объявляется для класса, если он не объявлен пользователем, оператор назначения базового класса для копирования / перемещения всегда скрыт соответствующим оператором назначения производного класса (13.5.3). Объявление-использование (7.3.3), которое вводит из базового класса оператор присваивания с типом параметра, который может быть оператором присваивания копирования / перемещения для производного класса, не считается явным объявлением такого оператора и делает не подавлять неявное объявление оператора производного класса; оператор, введенный объявлением использования, скрыт неявно объявленным оператором в производном классе.

0 голосов
/ 07 сентября 2011

Оператор присваивания не наследуется производным.Если вы используете перегруженный оператор присваивания в своем производном от вашей базы, вы можете столкнуться с нарезкой: sizeof(base) != sizeof(derived)

...