Почему нарезка некорневого базового класса дает правильный ответ?

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

#include <iostream>

using namespace std;class Dog{

public:
Dog( int x )
:x{x}
{

};

int x;

};class Spaniel: public Dog{

public:
Spaniel( int x, int y )
:Dog{x}, y{y}
{

}

int y;

};class Green{

public:
Green( int q )
:q{q}
{

}

int q;

};class GreenSpaniel: public Spaniel, public Green{

public:
GreenSpaniel( int x, int y, int q, int z )
:Spaniel{x,y}, Green{q}, z{z}
{

}

int z;

};int main(){

GreenSpaniel jerry{ 1,2,3,4 };

Green fred = jerry;

cout << fred.q << endl;  //correctly displays "3"
return 0;

}

Я ожидал, что он вернет 1, потому что базовый класс не был самым верхним (root), но он отображает 3. Итак, мой вопрос: почему / как он показывает правильный ответ и это безопасная практика? Как изменится ваш ответ, если у любого из классов будут виртуальные таблицы? Если вы не считаете это безопасным, есть ли у вас какие-либо обходные пути для копирования базового объекта без полномочий root из производного объекта?

Я запустил это в Linux под GCC 4.6.3 с помощью следующей команды:

g++ -std=c++0x main.cc

0

Решение

Происходит то, что fred создается с использованием конструктора копирования, синтезированного компилятором, который принимает const Green& в качестве аргумента. Он выполняет мелкую копию содержимого зеленой части Джерри.

вы бы видели тот же результат, если бы использовали

const Green& fred = jerry;

где копия не выполняется, вы просто получаете доступ к части Джерри Джерри, давая ему имя fred,

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

Конечно, вы можете определить свой собственный конструктор (ы) копирования / оператор (ы), имеющие другое поведение. Или вы можете просто запретить компилятору генерировать их

Традиционный способ справиться с этим — объявить конструктор частной копии и присвоение копии, а затем задокументировать, почему это так.
сделанный. В C ++ 2011 была представлена ​​новая альтернатива, объявляющая копию
конструктор и оператор присваивания копии, но помечая как
удален. Происхождение из некопируемого проще и понятнее, и
не требует дополнительной документации.

источник

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]