2011-01-05 4 views
2

Я написал несколько строк кода, которые, как я думаю, не следует компилировать. Я вызываю метод производного класса на указатель static_cast-эд на объект базового класса следующим образом:Метод вызова производного класса на объекте базового класса

class B {};  

class D: public B 
{ 
public: 
    void bar() { printf("%d\n", m_i); } 
private: 
    int m_i; 
}; 

int main() 
{ 
    B b; 
    D* d = static_cast<D*>(&b); 
    d->bar(); 
    return 0; 
} 

Значение печатается явно нездоровая, но если это даже компилировать? Как это сделать gcc?

+3

Почему он не должен компилироваться? Вы производите B как D. Для всего, что компилятор знает, он выполняет операции на D – Falmarri

+0

, пожалуйста, не используйте printf в коде C++. – BatchyX

+1

@BatchyX: 'printf' может быть ужасно опасным, но он значительно быстрее, чем' cout' и друзей. – Puppy

ответ

1

gcc не может гарантировать, что это неверно, за исключением достаточного количества случаев, когда это действительно не стоит проверять. Когда вы используете static_cast, вы обещаете компилятору, что знаете, что делаете.

Здесь есть два вида отливок. static_cast, то есть вы сообщаете компилятору, что указатель на базу IS является указателем на производный, и заткнись и продолжайте с ним. dynamic_cast, то есть вы просите компилятор проверить, действительно ли этот указатель на базу является указателем на производный. Вы использовали static_cast, поэтому компилятор заткнился и сделал, как вы сказали.

Редактировать: Джон точно указал, что в вашей иерархии наследования нет виртуальных функций, для которых вы должны быть уволены из C++, а dynamic_cast действителен только для виртуальных функций.

+0

'dynamic_cast' не будет работать в этом partucular случае, потому что типы не являются полиморфными. –

+0

@ Джон: Хорошая точка. Почему люди сохраняют код публикации с наследованием и виртуальными функциями? – Puppy

+0

Хорошо. Понял. Глупый вопрос. И во время выполнения он, вероятно, печатает содержимое местоположения в памяти, где переменная m_i была бы, если бы объект находился в классе D. Правильно? – 341008

0

Использование static_cast <> вы сказали компилятору: «Я знаю, что я делаю, что B * на самом деле D *, заткнись и просто делай то, что я говорю».

+0

Не совсем. 'static_cast' не будет компилироваться, если только два типа не связаны. Возможно, вы думаете о 'reinterpret_cast' –

+0

@ Джона Диблинга: в течение определенных проверок времени компиляции, используя static_cast <>, вы сообщаете компилятору« Я знаю лучше вас ». В результате вам лучше делать это правильно. –

+0

@ Джун Диблинг: Я сказал иначе? –

Смежные вопросы