Выделение объекта базового класса в лишенный класс - PullRequest
2 голосов
/ 21 октября 2011

Предположим, я создаю объекты двух классов:

BaseClass B;
DerievedClass D;

и затем я делаю:

B=D;
D=B;

Что является законным и почему.Этот вопрос задал интервьюер из C ++, связанного с Job.Я знаю в основном B = D;будет действительным (нарезка объекта);но так ли это, что D = B;будет действительным, только если B имеет конструктор по умолчанию?Да тогда почему?

Ответы [ 3 ]

6 голосов
/ 21 октября 2011
B=D;
D=B;

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


так ли, что D = B; будет действительным, только если B имеет конструктор по умолчанию?

номер

D=B будет действительным, только если D определил operator=, который принимает B в качестве аргумента.

Derived & operator=(const Base &base); //member of Derived

Base B;
Derived D;
D = B;     //allowed - assignment

Или, если вы сделаете это при инициализации D, он будет действителен, только если конструктор D примет B в качестве аргумента.

Derived(const Base &base); //a constructor of Derived

Base B;
Derived D = B; //allowed - initialization

Или B определил пользовательское преобразование в D.

operator Derived(); //member of Base

Base B;
Derived D = B; //allowed      - initialization
D = B;         //also allowed - assignment
0 голосов
/ 21 октября 2011

Не видя реализации классов, вы не можете предполагать, что любой из этих двух компонентов скомпилируется!

Первый случай: B=D

Он скомпилируется, если только оператор = Bбыл перегружен, и в этом случае даже B=B может быть незаконным.Все, что вы можете сказать, это то, что если B=B допустимо, то B=D также допустимо, поскольку D является допустимым экземпляром класса BaseClass.

Второй случай: D=B

Этот вопрос был должным образом обсужден Навазом.Короче говоря, вы должны явно разрешить это.Вы можете:

  1. Определить оператор равенства:

    DerivedClass::operator=(const BaseClass& copy)

  2. Определить оператор явного преобразования:

    BaseClass::operator DerivedClass() const

  3. Добавить конструктор в DerivedClass, который принимает BaseClass:

    DerivedClass::DerivedClass(const BaseClass&)

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

0 голосов
/ 21 октября 2011

Наваз прав.B = D является допустимым, поскольку D является экземпляром BaseClass и будет принят через конструктор копирования, сгенерированный компилятором BaseClass.

BaseClass::BaseClass( const BaseClass& other ) { ... } // Implicit

Этот конструктор копирования будет унаследован DerivedClass, НО при выполнении D = Bкомпилятор будет искать метод DerivedClass (const BaseClass &), которого не существует.

DerivedClass::DerivedClass( const DerivedClass& other ); // Implicit
DerivedClass::BaseClass( const BaseClass& other );       // Inherited
DerivedClass::DerivedClass( const BaseClass &other );    // Not defined!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...