Как избежать ошибки сегментации C ++ с указателем вне области видимости (полиморфизм) - PullRequest
0 голосов
/ 01 ноября 2019

Я получаю ошибку сегментации в своем коде из-за попытки получить доступ к значению указателя в блоке if / else, и я думаю, что это потому, что объекты выходят из области видимости.

Проблема в том, чтоМне нужно использовать полиморфизм и тип дочернего объекта, которому я назначаю указатели родительского типа, зависит от ввода в командной строке, поэтому я не уверен, как избежать if / else.

Код ниже. Я знаю, что имена переменных плохие, кстати, я просто упрощаю их ради этого вопроса.

P * p1;
P * p2;
B board = B();

if(strcmp(argv[1], "h") == 0) {
   H h = H(board);
   p1 = &h;
} else {
   C c = C(board);
   p1 = &c;
} //else


if(strcmp(argv[2], "h") == 0) {
   H h = H(board);
   p2 = &h;
} else {
   C c = C(board);
   p2 = &c;
} //else   


// Then, if I try to refer to pointer p1, I get a segmentation fault.
// I know why this happens, but am not sure how to fix it.
// For example, this code is problematic:

if(strcmp(argv[1], "h") == 0){
   string n;
   cin >> n;
   p1->setName(n);
} //if

Я получаю ошибку сегментации при обращении к указателям p1 и p2 после этого. Я знаю, что это потому, что объекты типа H и C выходят из области видимости после моих блоков if / else, но я не уверен, как мне это исправить. Будет ли работать объект H и C в куче? Или, может быть, объявлять объекты H и C вне оператора if?

Заранее благодарим за любую помощь.

Ответы [ 2 ]

2 голосов
/ 01 ноября 2019

Я рекомендую вам диагностировать источник проблемы.

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

if(strcmp(argv[1], "h") == 0) {
   p1 = new H(board);
} else {
   p1 = new C(board);
}

Сделайте то же самое для p2.

Добавьте код, чтобы освободить динамически выделенную память до конца функции.

delete p1;
delete p2;

Вы можете использовать умный указательчтобы облегчить освобождение.

std::unique_ptr<P> p1;
std::unique_ptr<P> p2;

...

if(strcmp(argv[1], "h") == 0) {
   p1.reset(new H(board));
} else {
   p1.reset(new C(board));
}

Используя std::unique_ptr, вам не понадобятся строки для удаления указателей.

1 голос
/ 01 ноября 2019

Вы можете выделить динамически. Я рекомендую использовать умный указатель . Вот пример:

std::unique_ptr<P> p1;
if(cond)
  p1.reset(new H(board));

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

...