如何使用 CRTP 创建少量对象?
How create few objects with CRTP?
我编写了一些小示例 CRTP 模式,以便更好地学习它并在更复杂的代码中使用它。
我想使用 CRTP,基 class 可以访问派生 class。好的,但我无法为我的基地创建一些对象 class。如果我首先为两个对象 Base<Derived1> base1; Base<Derived2> base2;
调用构造函数,然后从每个对象 base1.PrintDerived_FromA(); base2.PrintDerived_FromA();
第二次调用函数,我得到的结果是:
Base constr work
Base constr work
b_: 0
b_: 25
但是,我应该有:
Base constr work
Base constr work
b_: 9
b_: 25
如果我在构造函数之后立即调用函数,一切正常:
Base<Derived1> base1;
base1.PrintDerived_FromA();
Base<Derived2> base2;
base2.PrintDerived_FromA();
结果:
Base constr work
b_: 9
Base constr work
b_: 25
事实证明,新的构造函数调用覆盖了现有对象,但为什么呢?有可能解决这个问题吗?我只想使用 CRTP,没有虚拟功能。
#include <iostream>
template <class T>
class Base {
public:
Base();
void PrintDerived_FromA();
void InitializeDerived();
};
class Derived1 : public Base<Derived1> {
public:
Derived1(int b);
void PrintDerived();
void SetDerived(int b);
private:
int b_;
};
class Derived2 : public Base<Derived2> {
public:
Derived2(int b);
void PrintDerived();
void SetDerived(int b);
private:
int b_;
};
template <typename T>
Base<T>::Base() {
InitializeDerived();
std::cout << "Base constr work" << std::endl;
}
template <>
void Base<Derived1>::InitializeDerived() {
static_cast<Derived1*>(this)->SetDerived(9);
}
template <>
void Base<Derived2>::InitializeDerived() {
static_cast<Derived2*>(this)->SetDerived(25);
}
template <typename T>
void Base<T>::PrintDerived_FromA() {
static_cast<T*>(this)->PrintDerived();
}
Derived1::Derived1(int b) : b_(b), Base() {
std::cout << "Derived1 constr work" << std::endl;
}
void Derived1::PrintDerived() {
std::cout << "b_: " << b_ << std::endl;
}
void Derived1::SetDerived(int b) {
b_ = b;
}
Derived2::Derived2(int b) : b_(b), Base() {
std::cout << "Derived2 constr work" << std::endl;
}
void Derived2::PrintDerived() {
std::cout << "b_: " << b_ << std::endl;
}
void Derived2::SetDerived(int b) {
b_ = b;
}
int main() {
Base<Derived1> base1;
Base<Derived2> base2;
base1.PrintDerived_FromA();
base2.PrintDerived_FromA();
return 0;
}
static_cast<Derived1*>(this)
转换无效:this
指向 Base<Derived1>
类型的对象而不是 Derived1
。因此取消引用生成的指针会导致未定义的行为。为了使 CRTP 工作,您需要创建派生对象 类.
我编写了一些小示例 CRTP 模式,以便更好地学习它并在更复杂的代码中使用它。
我想使用 CRTP,基 class 可以访问派生 class。好的,但我无法为我的基地创建一些对象 class。如果我首先为两个对象 Base<Derived1> base1; Base<Derived2> base2;
调用构造函数,然后从每个对象 base1.PrintDerived_FromA(); base2.PrintDerived_FromA();
第二次调用函数,我得到的结果是:
Base constr work
Base constr work
b_: 0
b_: 25
但是,我应该有:
Base constr work
Base constr work
b_: 9
b_: 25
如果我在构造函数之后立即调用函数,一切正常:
Base<Derived1> base1;
base1.PrintDerived_FromA();
Base<Derived2> base2;
base2.PrintDerived_FromA();
结果:
Base constr work
b_: 9
Base constr work
b_: 25
事实证明,新的构造函数调用覆盖了现有对象,但为什么呢?有可能解决这个问题吗?我只想使用 CRTP,没有虚拟功能。
#include <iostream>
template <class T>
class Base {
public:
Base();
void PrintDerived_FromA();
void InitializeDerived();
};
class Derived1 : public Base<Derived1> {
public:
Derived1(int b);
void PrintDerived();
void SetDerived(int b);
private:
int b_;
};
class Derived2 : public Base<Derived2> {
public:
Derived2(int b);
void PrintDerived();
void SetDerived(int b);
private:
int b_;
};
template <typename T>
Base<T>::Base() {
InitializeDerived();
std::cout << "Base constr work" << std::endl;
}
template <>
void Base<Derived1>::InitializeDerived() {
static_cast<Derived1*>(this)->SetDerived(9);
}
template <>
void Base<Derived2>::InitializeDerived() {
static_cast<Derived2*>(this)->SetDerived(25);
}
template <typename T>
void Base<T>::PrintDerived_FromA() {
static_cast<T*>(this)->PrintDerived();
}
Derived1::Derived1(int b) : b_(b), Base() {
std::cout << "Derived1 constr work" << std::endl;
}
void Derived1::PrintDerived() {
std::cout << "b_: " << b_ << std::endl;
}
void Derived1::SetDerived(int b) {
b_ = b;
}
Derived2::Derived2(int b) : b_(b), Base() {
std::cout << "Derived2 constr work" << std::endl;
}
void Derived2::PrintDerived() {
std::cout << "b_: " << b_ << std::endl;
}
void Derived2::SetDerived(int b) {
b_ = b;
}
int main() {
Base<Derived1> base1;
Base<Derived2> base2;
base1.PrintDerived_FromA();
base2.PrintDerived_FromA();
return 0;
}
static_cast<Derived1*>(this)
转换无效:this
指向 Base<Derived1>
类型的对象而不是 Derived1
。因此取消引用生成的指针会导致未定义的行为。为了使 CRTP 工作,您需要创建派生对象 类.