static_cast вывел этот объект в базовый класс в Stack Overflow

При чтении предмета 27 сверните приведение Эффективный C ++, он говорит, что не пытайтесь использовать static_cast транслировать *this в производном классе до базового класса. Это потому что static_cast<Base>(*this) создаст временный объект базового класса. Я попробовал следующий пример, однако он всегда выдает 10 с использованием разных компиляторов, таких как clang 3.8 и gcc 4.9, 5.3.

Я ошибся?

  #include <iostream>

class A {
public:
int a;
virtual void foo() {std::cout << a << std::endl;}
};

class B : public A {
public:
int b;
void foo ()  { static_cast<A>(*this).foo();}
};int main () {
B b;
b.a = 10;
b.foo();

return 0;
}

Вопрос почему static_cast создаст временный объект.

1

Решение

Более значимым примером будет этот:

#include <iostream>

class A {
public:
virtual void foo() { std::cout << "A" << std::endl; }
};

class B : public A {
public:
virtual void foo() { std::cout << "B" << std::endl; }
void bar ()  { static_cast<A>(*this).foo(); }
};

int main () {
B b;
b.bar();
}

Я бы ожидал bar печатать B, за foo это переопределенный метод. Это печатает A вместо.
Ну, это правильно с точки зрения языка, не так хорошо с точки зрения разработчика, который ожидал совершенно другого результата.

Это работает, если вы используете вместо этого следующий класс:

class B : public A {
public:
virtual void foo() { std::cout << "B" << std::endl; }
void bar ()  { static_cast<A*>(this)->foo(); }
};

Также следующее работает как ожидалось (добавлено для ясности, благодаря @MORTAL в комментариях):

class B : public A {
public:
virtual void foo() { std::cout << "B" << std::endl; }
void bar ()  { static_cast<A&>(*this).foo(); }
};

Во всяком случае, проблема, с которой вы сталкиваетесь, называется нарезка.
Вот почему с помощью static_cast<A>(*this) не рекомендуется, если вы не знаете, что делаете.

Увидеть Вот для дальнейших деталей.

2

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

Прежде всего вам не нужно разыгрывать Derived -> Base, потому что это происходит автоматически. И да, static_cast создаст объект типа, к которому вы приводите.
В вашем случае, чтобы включить полиморфизм, вы можете использовать ссылки или указатели:

int main(){
B b;
A &a = b; // no explicit cast needed
a.foo(); // will call B::foo

//OR

B *bPtr = new B;
A *aPtr = bPtr; // no explicit cast needed
aPtr->foo(); // same as above
}
-1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector