Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么模板<;typename T>;在C+中计算为Foo而不是Bar+;_C++_Pointers_Inheritance_Polymorphism_Generic Programming - Fatal编程技术网

C++ 为什么模板<;typename T>;在C+中计算为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(

在这段代码中,为什么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(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&
绑定到
条&