перегрузка оператора — Как создать экземпляр подкласса в переменной-члене в C ++?

У меня есть огромная база кода C ++, с которой я работаю.

Я хочу представить новый подкласс и использовать его во множестве различных контекстов, однако у моего обученного ума Java есть проблемы с этим в C ++.

Я хочу минимизировать изменения кода. Итак, мой основной класс интересов (BAR ниже) имеет переменную-член класса FOO, Я хочу сделать подкласс FOO называется FOOSUBCLASS, В Java это тривиально. Объекты хранятся по ссылке по умолчанию. Этот код не делает этого (как показано ниже), могу ли я массажировать этот код, не меняя интерфейсы (и не вводя ссылки), и все же заставить мое приложение работать?

class FOO {
};

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

class BAR {
public:
BAR(const FOO foo) { _foo = foo;}
private:
FOO _foo;
};

Ниже мое главное:

FOOSUBCLASS fsc(1);
BAR b(fsc);

Но это не компилируется в VS2005. Это говорит:

‘type cast’: преобразование из ‘FOOSUBCLASS *’ в ‘const FOO &’существует, но недоступен

Получите ту же ошибку компилятора, если я добавлю очевидный другой конструктор BAR

BAR(const FOOSUBCLASS foo) { _foo = foo;}

Я понимаю, что C ++ будет копировать данные из FOOSUBCLASS в объект класса FOO, (используя оператор присваивания или его переопределенную версию) Но в моем случае у меня есть дополнительные переменные-члены в FOOSUBCLASS (и некоторые переопределенные функции-члены), поэтому я просто не хочу, чтобы это делалось. Я хочу, чтобы моя переменная-член _foo чтобы действительно быть типом FOOSUBCLASS в некоторых контекстах и FOO в других. Это вообще возможно?

Спасибо за ваши мысли.

2

Решение

Вы не можете сделать это так, как написали сейчас, извините. Это называется «нарезка», и больше информации об этом можно найти здесь: Что такое нарезка объектов?

Если вы хотите, чтобы ваш _foo Чтобы член был полиморфным, вам нужно использовать указатель или ссылку. Будьте внимательны к управлению жизненным циклом, когда вы делаете такие вещи, конечно.

2

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

Сделать базовый класс общедоступным

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

Кроме того, остерегайтесь нарезки в BAR конструктор

Назначьте указатель / ссылку, чтобы избежать этого:

class FOO
{
};

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

class BAR
{
public:
BAR(const FOO& foo) : _foo(foo)
{
}
private:
FOO& _foo;
};

Примечание: я использовал синтаксис списка инициализаторов вместо присваиваний в теле конструктора.

2

Сначала в C ++ классах по умолчанию используют private наследовать от своих базовых классов, это означает, что FOOSUBCLASS это FOO но преобразование является внутренним и не доступно для вас. Итак, сначала преобразовать class FOOSUBCLASS : FOO в class FOOSUBCLASS : public FOO а второй в Java каждый это ссылка, так что вы можете сказать,

FOOSUBCLASS fs;
FOO f = fs;

но в C ++ у нас есть ссылки и не-ссылки и использование FOO f создать не ссылку, которая на самом деле является объектом, так FOO f = fs только копия FOO часть fs в f и не вызывает FOO ссылка на FOOSUBCLASS Для достижения этого вы должны использовать указатель или ссылку или умные указатели. Например, вы можете сказать:

FOOSUBCLASS* fs = new FOOSUBCLASS;
FOO* f = fs;   // Use pointer is OK
FOO& rf = fs;  // A reference of fs as a FOO
std::auto_ptr<FOO> spf( fs );  // OK, but for this destructor must be virtual
1

В дополнение к пользователю sehe, рассмотрите возможность передачи ссылки, а не передачи по значению в конструктор BAR.


class BAR {
public:
BAR(const FOO& foo) { _foo = foo;}
private:
const FOO& _foo;
};

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