подкласс — потенциальный обходной путь для нарезки C ++?

У меня есть проблема нарезки C ++. Я новичок в C ++, так что, может быть, просто слишком глуп, чтобы понять, что это невозможно сделать … Я пробовал различные обходные пути, и мой текущий лучший подход выглядит ниже. (Мне нужно сделать что-то подобное, чтобы избежать изменения тонны интерфейсов в очень большой устаревшей кодовой базе. Ни в коем случае не утверждая, что это элегантный стиль !!)

Проблемы с компиляцией. Звучит ли идея? Или весь подход обречен на провал? Конструкторы для ссылок, кажется, проблема. Я читал «Язык программирования С ++» Страуструпа (или, по крайней мере, то, что я считал соответствующими разделами), но это не помогло.

class FOO {};

class FOOSUBCLASS : public FOO {
public:
FOOSUBCLASS(const int id = 0) : _id(id) {}
private:
int _id;
};

class BAR {
public:
BAR(const FOO foo) : _foo(foo), _realFoo(&_foo) { }

BAR(const FOOSUBCLASS foosc) : _foosc(foosc), _realFoo(&_foosc) {}
private:
FOO _foo;
FOOSUBCLASS _foosc;
FOO& _realFoo;
};

Компилятору не нравится мой _realFoo(&_foo) линия. Я хотел бы ссылку на _foo, просто чтобы быть ссылкой из переменной-члена в классе. Разве это не возможно в C ++?

Вот конкретная ошибка VS2005:

'initializing' : cannot convert from 'FOO *' to 'FOO &'

1

Решение

_foo это FOO&,
&_foo это FOO*,
Компилятор cannot convert from 'FOO *' to 'FOO &',
что ты хочешь ..., _realFoo(_foo)

Не связано: что вы, вероятно, на самом деле хотите std::unique_ptr<FOO> член вместо. Это будет намного меньше и намного менее подвержено ошибкам.

Структура, как у вас есть сейчас, содержит полный и законченный экземпляр FOOи полный и полный экземпляр FOOSUBCLASSи ссылка. В наименее положить два FOO штуковин в союзе, поэтому размер BAR только немного больше, чем самый большой FOO производное. Это, вероятно, будет использовать ту же память, что и unique_ptr<FOO>, К несчастью, unions — распространенный источник ошибок в C и C ++.

Другая проблема, если кто-то приходит и пишет

class FOOSOMETHINGELSE : public FOO {
int buffer[1024];
};

Тогда вам придется пойти и найти BAR Класс и изменить его, сделать его еще больше, и перекомпилировать весь ваш код, который использует BAR везде. Принимая во внимание, что если вы использовали unique_ptr<FOO>тогда вам не придется менять BAR или перекомпилировать что-нибудь. Так меньше вероятность ошибки.

2

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

Здесь есть несколько проблем. Вы правильно идентифицируете один из них как нарезку, но нарезка не вызывает ошибок во время компиляции (что делает его таким ужасным …). Ответ Mooing Duck должен решить вашу проблему с компиляцией, но проблема срезов остается. Предположим, у вас есть

FOO *x = new FOOSUBCLASS;
BAR y(*x);

Это приведет к нарезке, потому что будет вызван следующий конструктор:

BAR(const FOO foo) : _foo(foo), _realFoo(&_foo) { }

и он принимает свой аргумент по значению, то есть будет происходить копирование из производного в базовое.

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

Я уверен, что все, что вы хотите сделать здесь, это позволить BAR объект относится к объекту, который является либо FOO объект или что-то полученное из него — правильно? В этом случае (и при условии, что время жизни FOO объект превышает таковой из BAR объект), все что вам нужно это:

class BAR {
public:
explicit BAR(FOO& foo) : _foo(foo) {}

private:
FOO& _foo;
};
1

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