问题描述
我正在构建一个 CRTP 接口并注意到一些未定义的行为。因此,我构建了一些示例代码来缩小问题的范围。
#include <iostream>
template <typename T>
class Base {
public:
int a() const { return static_cast<T const&>(*this).a_IMPL(); }
int b() const { return static_cast<T const&>(*this).b_IMPL(); }
int c() const { return static_cast<T const&>(*this).c_IMPL(); }
};
class A : public Base<A> {
public:
A(int a,int b,int c) : _a(a),_b(b),_c(c) {}
int a_IMPL() const { return _a; }
int b_IMPL() const { return _b; }
int c_IMPL() const { return _c; }
private:
int _a;
int _b;
int _c;
};
template <typename T>
void foo(const T& v) {
std::cout << "foo()" << std::endl;
std::cout << "a() = " << static_cast<Base<T>>(v).a() << std::endl;
std::cout << "b() = " << static_cast<Base<T>>(v).b() << std::endl;
std::cout << "c() = " << static_cast<Base<T>>(v).c() << std::endl;
}
int main() {
A v(10,20,30);
std::cout << "a() = " << v.a() << std::endl;
std::cout << "b() = " << v.b() << std::endl;
std::cout << "c() = " << v.c() << std::endl;
foo(v);
return 0;
}
a() = 10
b() = 20
c() = 30
foo()
a() = 134217855
b() = 0
c() = -917692416
似乎在将实现 CRTP“接口”的子类转换为接口本身时存在一些问题。这对我来说没有意义,因为类 A 显然是从 Base 继承的,所以我不应该能够将 A 的实例转换为 Base 吗?
谢谢!
解决方法
在投射到 Base<T>
时复制和切片。
改为转换为 const Base<T>&
:
std::cout << "a() = " << static_cast<const Base<T>&>(v).a() << std::endl;
std::cout << "b() = " << static_cast<const Base<T>&>(v).b() << std::endl;
std::cout << "c() = " << static_cast<const Base<T>&>(v).c() << std::endl;
,
事实证明我错误地转换为一个值而不是一个引用
std::cout << "a() = " << static_cast<Base<T>>(v).a() << std::endl;
应该变成
std::cout << "a() = " << static_cast<const Base<T>&>(v).a() << std::endl;