У меня есть этот простой код:
class A {
public:
int m;
};
class B : public A {
public:
B(const B& b) { /*...*/ }
B(const A& a) { /*...*/ }
int n;
};
const A& function()
{
static A a;
return a;
}
int main()
{
const B& a = function();
const int x = a.n; // !!!!! Error: probably reads some random mess
/* ... */
B b2 = function();
/* ... */
return 0;
}
В этом коде я демонстрирую, что может произойти, если вы по ошибке напишите const B& a = function()
вместо const A& a = function()
, И компилятор не ловит эту ошибку! Чтобы отловить эту ошибку во время компиляции, конструктор B(const A& a)
должно быть explicit
, Но разметка конструктора explicit
отключает способность делать B b2 = function();
— это должно быть написано более уродливо: B b2(function());
Вопрос: Существует ли какой-нибудь способ отловить этот тип ошибки во время компиляции, сохраняя возможность написать это?
B b2 = function();
РЕДАКТИРОВАТЬ: Как утверждают @ditskowitch и @ n.m. То, что я предполагаю быть ошибкой, не является ошибкой. Для этого явный конструктор не нужен. Теоретически это может быть проблемой, только если зависимый код ожидает, что ссылка, возвращаемая функцией (), указывает на какой-то адрес, как показывал @Rory Yorke
Компилятор ведет себя правильно: так как ваш B class
имеет конструктор, принимающий const A&
— вы на самом деле делаете это B
может быть должным образом создан из экземпляра A
, Так что не должно быть никакого «случайного беспорядка» в x
, но значение, которое конструктор присваивает n
при построении из экземпляра A
Вопрос: существует ли какой-нибудь способ отловить этот тип ошибки во время компиляции, сохраняя возможность написать это?
Маркировка вашего конструктора «B из A» как explicit
:
explicit B(const A& a) { /*...*/ }
не позволит компилятору использовать его для автоматического преобразования. Увидеть этот вопрос для дополнительной информации.