Это действительный уныние

0

У меня есть код cpp, где в классе c происходит из класса b, а класс b - из класса a.

Теперь класс b имеет некоторый открытый элемент данных. Поэтому я создаю экземпляр класса c на куче, передавая его указатель на другой класс как указатель на a, и там он понижает указатель на указатель класса b, а затем печатает общедоступные переменные класса b.

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

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

#include <iostream>
using namespace std;


class grand
{
};
class parent : public grand
{
    public : parent(){i=0;}
    int i;
    parent(int j){ i = j;}
    void set(int j){i = j;}
};

class child : public parent{


public: child(){};
};

void print ( grand* ptr)
{
    parent *p = (parent*) ptr;
    std::cout << std::endl << p->i << std::endl;
}

int main() {
    // your code goes here
    child c;
    c.set(9);
    print(&c);
    return 0;
}

благодаря

  • 1
    Кастинг в стиле C следует избегать здесь. Вероятно, вам следует ознакомиться с различными методами литья и их применениями. В этом случае вы должны изменить определение print чтобы принимать только parent* и позволить компилятору приводить за вас, потому что вы не можете быть уверены, что ваше приведение действительно в противном случае.
  • 0
    Использует ли ваш реальный код множественное наследование случайно?
Теги:
pointers

3 ответа

4
Лучший ответ

Является ли это действительным понижением.

Да. Ваш бросок внутренне применяет static_cast, который, согласно §5.2.9/11, даст вам правильный результат. Если аргумент для ptr не указывает на parent, результат отбрасывания не определен - и так будет выполняться следующий код.

Downcasting полиморфных типов в C++ работает через dynamic_cast. Ваш grand класс выше не является полиморфным - вы должны добавить по крайней мере виртуального деструктора к grand чтобы сделать его полиморфным. В противном случае вы получите ошибку компилятора со следующим кодом.

parent *p = dynamic_cast<parent*>(ptr); // Once grand is polymorphic...

И проверьте, отличен ли результат p от нуля. Только этот метод показывает (во время выполнения), работает ли бросок! Все остальные либо вызывают неопределенное поведение, либо неопределенные ненулевые значения.

Некоторые примечания:

  • Downcasting почти всегда является признаком плохого дизайна. Избегайте его, если это возможно, используя, например, виртуальные (печатные) функции.
  • print должен принимать указатель на const поскольку он не изменяет никаких элементов данных.
0

Вместо того, чтобы использовать C-стиль, вы должны применить dynamic_cast или хотя бы static_cast если по какой-либо причине вы компилируете без RTTI (информация о типе времени выполнения).

Сценарий C-стиля совпадает с reinterpret_cast, который, по сути, интерпретирует память, на которую указывает, как если бы там был создан объект типа parent. Но каждый компилятор может иметь разную структуру памяти производных классов, поэтому может работать в некоторых обстоятельствах, но нет гарантии.

  • 0
    На самом деле, приведение в стиле C делает кучу приведений, и reinterpret_cast - только последнее средство.
  • 2
    В этом случае приведение в стиле C эквивалентно static_cast , так как существует допустимый переход от grand к parent . Но этого все же следует избегать; он возвращается к reinterpret_cast , давая ложные результаты времени выполнения, где static_cast даст полезную ошибку во время компиляции.
0

Ваш код, как написано, действительно действителен, но есть куча замечаний, которые я хотел бы сделать. Обратите внимание, что он действителен только потому, что объект, который вы передаете для print является parent или дополнительным производным классом.

Затем обратите внимание, что, поскольку вы должны отдать его функции print гораздо безопаснее просто менять подпись функции, чтобы взять parent вместо grand и тогда вам не нужно беспокоиться о кастинге.

Затем обратите внимание, что вероятной причиной вашей проблемы является то, что в файле, который выполняет бросок, компилятор не видит отношения между grand и parent поэтому ваш стиль C-стиля возвращается к reinterpret_cast который не является тем, что вы хотите. Если вы не можете изменить подпись print по крайней мере, измените ее на static_cast (или, возможно, dynamic_cast, но вы не можете сделать это в своем примере, потому что классы не являются полиморфными), чтобы компилятор не смог скомпилировать его не вижу отношения класса.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню