C++ 为什么模板<;typename T>;在C+中计算为Foo而不是Bar+;
在这段代码中,为什么typename T(在Test(…)函数中)计算为Foo类型而不是Bar类型?我怎样才能改变它,使它成为类型栏C++ 为什么模板<;typename T>;在C+中计算为Foo而不是Bar+;,c++,pointers,inheritance,polymorphism,generic-programming,C++,Pointers,Inheritance,Polymorphism,Generic Programming,在这段代码中,为什么typename T(在Test(…)函数中)计算为Foo类型而不是Bar类型?我怎样才能改变它,使它成为类型栏 #include <typeinfo> using namespace std; struct Foo { virtual ~Foo() { } }; struct Bar : public Foo { }; template<typename T> bool Test(T foo) { return (typeid(
#include <typeinfo>
using namespace std;
struct Foo
{
virtual ~Foo() { }
};
struct Bar : public Foo
{
};
template<typename T>
bool Test(T foo)
{
return (typeid(foo) == typeid(Bar));
}
int main()
{
Bar bar;
Foo *foo = &bar;
bool THIS_IS_TRUE = (typeid(*foo) == typeid(Bar));
bool WHY_ISNT_THIS = Test(*foo);
return 0;
}
#包括
使用名称空间std;
结构Foo
{
虚拟~Foo(){}
};
结构栏:公共Foo
{
};
模板
布尔测试(T-foo)
{
返回(typeid(foo)=typeid(Bar));
}
int main()
{
酒吧;
Foo*Foo=&bar;
bool THIS_IS_TRUE=(typeid(*foo)=typeid(Bar));
bool为什么不这=测试(*foo);
返回0;
}
必须保留指针或通过引用传递值,不能通过副本传递变量(通过值传递)
试试这个:
template<typename T>
bool Test(T foo)
{
return (typeid(*foo) == typeid(Bar));
}
int main()
{
Bar bar;
Foo *foo = &bar;
bool THIS_IS_TRUE = (typeid(*foo) == typeid(Bar));
bool WHY_ISNT_THIS = Test(foo);
return 0;
}
模板
布尔测试(T-foo)
{
返回(typeid(*foo)=typeid(Bar));
}
int main()
{
酒吧;
Foo*Foo=&bar;
bool THIS_IS_TRUE=(typeid(*foo)=typeid(Bar));
bool为什么不是这个=测试(foo);
返回0;
}
模板是基于静态类型而不是动态类型推导出来的。代码是静态绑定的,并根据编译器在编译时知道的内容创建,与运行时的类型无关。此外,当您通过值传递*foo
时,您仍然在切片对象。模板是在编译时完成的,因此它们无法确定您传递的运行时类型
无论如何,由于您是通过值传递的,因此您将转换并切片到对象,这将丢失有关原始类型Bar
的信息。请尝试引用:
template<typename T>
bool Test(T& foo)
{
return (typeid(foo) == typeid(Bar));
}
模板
布尔测试(T&foo)
{
返回(typeid(foo)=typeid(Bar));
}
T
仍将被推断为Foo
,但是typeid(Foo)
应该是Bar
您想做的事情不起作用。这里是另一种方法,我基本上构建自己类型的基础架构:
#include <functional>
struct Base {
protected:
virtual ~Base() {}
Base() {}
public:
virtual size_t SizeRequired() const = 0;
virtual std::function<Base*(unsigned char* buffer)> Constructor() const = 0;
// note that standard delete is not standards compliant, because the memory
// was allocated as an array of unsigned char's
void SelfDelete() {
SelfDestroy();
delete[] reinterpret_cast<unsigned char*>(this);
}
// you can also create these things in other storage locations:
void SelfDestroy() {
this->~Base();
}
static void Delete( Base* b ) {
if (b)
b->SelfDelete();
}
std::function<Base*()> AllocateAndConstructor() const {
size_t required = this->SizeRequired();
auto constructor = this->Constructor();
return [required, constructor]()->Base* {
unsigned char* buff = new unsigned char[ required ];
return constructor( buff );
};
}
};
// CRTP class (google CRTP if you are confused what I'm doing)
template<typename Child>
struct BaseHelper: Base {
static Base* Construct(unsigned char* buffer) {
return new(buffer) Child();
}
static Base* Create() {
unsigned char* buff = new unsigned char[ sizeof(Child) ];
return Construct( buff );
};
virtual size_t SizeRequired() const {
return sizeof(Child);
}
virtual std::function<Base*(unsigned char* buffer)> Constructor() const {
return &BaseHelper<Child>::Construct;
}
};
// use:
struct Bar: BaseHelper<Bar> {
};
struct Foo: BaseHelper<Foo> {
};
Base* test(Base* b) {
auto creator = b->AllocateAndConstructor();
return creator();
}
#include <iostream>
int main() {
Base* b = Bar::Create(); // creates a Bar
Base* b2 = test(b); // creates another Bar, because b is a Bar
Base* f = Foo::Create(); // creates a Foo
Base* f2 = test(f); // creates another Foo, because f is a Foo
std::cout << (typeid(*b) == typeid(*b2)) << " == 1\n";
std::cout << (typeid(*f) == typeid(*f2)) << " == 1\n";
std::cout << (typeid(*f) == typeid(*b)) << " == 0\n";
Base::Delete(b);
Base::Delete(b2);
Base::Delete(f);
Base::Delete(f2);
Base::Delete(0); // does not crash
};
#包括
结构基{
受保护的:
虚拟~Base(){}
Base(){}
公众:
虚拟大小\u t size required()常量=0;
虚拟std::函数构造函数()常量=0;
//请注意,standard delete不符合标准,因为内存
//被分配为未签名字符的数组
void SelfDelete(){
自我毁灭();
删除[]重新解释(本);
}
//您还可以在其他存储位置创建这些内容:
void SelfDestroy(){
这个->~Base();
}
静态无效删除(基本*b){
如果(b)
b->SelfDelete();
}
std::函数AllocateAndConstructor()const{
所需大小=此->所需大小();
自动构造函数=此->构造函数();
返回[required,constructor]()->Base*{
unsigned char*buff=新的unsigned char[必需];
返回构造函数(buff);
};
}
};
//CRTP类(如果你不明白我在做什么,用谷歌CRTP)
模板
结构BaseHelper:Base{
静态基*构造(无符号字符*缓冲区){
返回新的(缓冲区)子项();
}
静态基*Create(){
unsigned char*buff=新的unsigned char[sizeof(Child)];
返回构造(buff);
};
虚拟大小\u t size required()常量{
返回sizeof(Child);
}
虚拟std::函数构造函数()常量{
return&BaseHelper::Construct;
}
};
//使用:
结构栏:BaseHelper{
};
结构Foo:BaseHelper{
};
基本*测试(基本*b){
自动创建者=b->AllocateAndConstructor();
返回创建者();
}
#包括
int main(){
Base*b=Bar::Create();//创建一个条
Base*b2=test(b);//创建另一个条,因为b是条
Base*f=Foo::Create();//创建一个Foo
Base*f2=test(f);//创建另一个Foo,因为f是一个Foo
std::有没有办法让T变成Bar,这样我就可以在foo上使用decltype并创建一个新的Bar对象?@David听起来你想要的是首先打破泛型代码的观点。不管怎样,如果你想这样做,只要用Bar
调用Test
。@David:当你传递一个Foo
你不会让t
变成Bar
!即使你尝试使用Test(*Foo)
等强制它,它也不会工作,因为编译器会拒绝将Foo&
绑定到条&
。