Инициализация членов производного класса (C ++) - PullRequest
0 голосов
/ 11 мая 2011

Каков предпочтительный метод для инициализации производного класса, который был приведен из его базового класса?

Рассмотрим следующий сценарий:

    class A{
        public:
           A();
           ~A();
    }

    class B : public A{
        public:
           B() {m_b = 0.0;};
           ~B();
           float GetValue(){return m_b;};

        private: 
           float m_b;
    }


    A* a = new A;
    B* b = static_cast<B*>(a);

    float val = b->GetValue();   // This was never initialized because it was not constructed

Мое текущее решение - вручную вызвать Initialize() Функция, которая будет выполнять необходимые инициализации, как это сделал бы конструктор.

Хотя это выглядит неаккуратно и должен быть лучший / более чистый метод.

Любая помощь и руководство очень приветствуются!

Ответы [ 6 ]

5 голосов
/ 11 мая 2011

Это ошибочная конструкция:

A* a = new A;
B* b = static_cast<B*>(a);

РЕДАКТИРОВАТЬ

Это действительно должно быть:

B* b = new B();

Так как, как указал sbiout, A не имеет виртуальной функции GetValue (), поэтому ее нельзя вызывать из A.

Не делать static_cast из A * в B *.

2 голосов
/ 11 мая 2011

Вы приводите родительский объект в объект производного типа. Это совершенно неправильно. Объект класса A не имеет члена m_b для инициализации.

0 голосов
/ 11 мая 2011
B* b = static_cast<B*>(a);

Вы должны использовать static_cast, только если вы знаете, что a фактически указывает на объект B или класс, производный от B, что явно не так.

Это неверное утверждение.
Действительная последовательность должна быть:

 A* a = new B();
 B* b = static_cast<B*>(a);

a теперь указывает на объект типа B. Это можно сделать потому, что Указатель на объект базового класса всегда может указывать на объекты производного класса, если он является открытым производным.

Теперь вы можете использовать static_cast, потому что вы точно знаете, что a фактически указывает на объект class B.
Могут быть сценарии, в которых один не знает об иерархии классов и в таких сценариях нельзя использовать static_cast C ++ предоставляет другой тип приведения, называемый Dynamic_cast, в таких сценариях он возвращает нулевой указатель, если приведение не является допустимым в случае указателей или выбросить исключение в случае ссылок.

Обратите внимание: Dynamic_Cast работает только с полиморфными классами.

0 голосов
/ 11 мая 2011

У вас нет экземпляра производного класса для инициализации - у вас есть только экземпляр базового класса. Все что делает 1static_cast1 - это заставляет компилятор разрешать вам обращаться с базовым классом как с производным классом.

Вместо этого, чтобы создать B, вы должны сделать следующее:

A* a = new B;

Это вызовет конструктор B, инициализируя m_b в 0.0.

0 голосов
/ 11 мая 2011

Код, который вы описали, опасен и недопустим, поскольку B - это A, но не наоборот. Это будет действительно:

B* b = new B;
A* a = dynamic_cast<A*>(b);
0 голосов
/ 11 мая 2011

Я не уверен, что это действительно так, потому что объект был создан с sizeof(A), а sizeof(B) явно больше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...