В настоящее время я играю с CRTP и сталкиваюсь с проблемой испорченной переменной-члена в производном классе, имеющей значение мусора (в настоящее время существует 4 уровня полиморфизма, причем самый верхний базовый класс называется «A»). "и самый нижний наиболее производный класс называется" D ").
Вот некоторый код, который отображает пример этой проблемы:
//A.hpp
template <class TB>
class A {
public:
A();
void CRTP_func();
};
template <class TB>
A<TB>::A() {
std::cout << "A constructor called!" << std::endl;
}
template<class TB>
void A<TB>::CRTP_func() {
std::cout << "CRTP_index called in A" << std::endl;
static_cast<TB*>(this)->CRTP_func2();
}
//B.hpp
#include "A.hpp"
#include <vector>
template<class TC>
class B : public A<B<TC>>
{
public:
B();
void CRTP_func2();
};
template<class TC>
B<TC>::B() {
std::cout << "B constructor called!" << std::endl;
}
template<class TC>
void B<TC>::CRTP_func2() {
std::cout << "CRTP_func called in B" << std::endl;
static_cast<TC*>(this)->CRTP_func3();
}
//C.hpp
#include "B.hpp"
template<class TD>
class C : B<C<TD>> {
public:
C();
void CRTP_func3();
int x;
};
template<class TD>
C<TD>::C() {
std::cout << "C constructor called" << std::endl;
}
template<class TD>
void C<TD>::CRTP_func3() {
std::cout << "CRTP_index3 called in C" << std::endl;
static_cast<TD*>(this)->CRTP_func4();
}
//D.hpp
#include "C.hpp"
class D : C<D> {
public:
D();
bool onInit();
void CRTP_func4();
C<D> top;
int y = 0;
};
D::D() {
std::cout << "D constructor called!" << std::endl;
}
bool D::onInit() {
std::cout << "D onInit called!" << std::endl;
y = 5;
return true;
}
void D::CRTP_func4() {
std::cout << y << std::endl;
std::cout << "CRTP_index4 called in D! " << std::endl;
}
//main.hpp
int main {
D * D_ptr = new D();
D_ptr->onInit();
D_ptr->top.CRTP_func3();
return 0;
}
Как видите, A - это базовый класс, а D - это производный класс как таковой:
A<B<C<D>>>
Вывод этой программы следующий:
A constructor called!
B constructor called!
C constructor called
A constructor called!
B constructor called!
C constructor called
D constructor called!
D onInit called!
CRTP_index3 called in C
-33686019
CRTP_index4 called in D!
Значение -33686019 распечатывается в D.hpp, где значение y печатается и устанавливается на 5 при инициализации. После небольшого копания я проверил значение в main.cpp, и оно установлено на 5 даже после выполнения этих вызовов CRTP, но выводится значение мусора.
После еще одной отладки я понял, что удаление строки
int x;
в B.hpp решает эту проблему, поэтому я думаю, что проблема связана с некоторым смещением, но я не уверен, почему это произойдет. Кто-нибудь знает, почему это произошло или как это исправить?
Извините за длинный пост и неоднозначный код, я попытался убрать большую часть сложности и максимально упростить код ради поста.
UPDATE:
Благодаря комментариям ниже я понял, как исправить мою проблему. Вместо использования D::top
лучшим подходом является создание указателя в главном файле следующим образом:
C<D> * C_ptr = static_cast<C<D>*>(D_ptr);
, а затем позвоните CRTP_func3()
оттуда так:
C_ptr->CRTP_func3();
Работает как задумано.