【问题标题】:template<class T> error模板<class T> 错误
【发布时间】:2011-05-23 09:25:15
【问题描述】:

我有一个:header.cpp、header.hpp 和一个 test_header.cpp。

在 header.hpp 我有:

class MyClass
  {
    public;
    MyClass();
    std::string name;
    //...code with other variables,methods;

 class MySecondClass
  {

    public:
    MySecondClass();

    std::string surname;
    //..code with other variables,methods

  }*MySC;

   public:
   template<class T>
   bool method(T& obj);

    {



    if (typeid(MyClass)=typeid(obj))
     {
       MyClass *s= new MyClass();
        *s=obj //i want to save everything that i have in obj into s;
        //call  method "MyMethod" and work with s

    }
     else if (typeid(MyClass::MySecondClass)=typeid(obj))
      {
        MyClass::MySecondClass *s1= new MyClass::MySecondClass();
        *s1 = obj;
        //call "MyMethod" and work with s1;
      }
     return true;
  }

}*mycls;

在 test_header.cpp 我有

{
  MyClass *mycls = new MyClass();
  MyClass::MySecondClass *mysec_cls= new MyClass::MySecondClass();

   if (mycls->method<MyClass>(*mycls) 
              {//code
               }
   if (mycls->method<MyClass::MySecondClass>(*mysec_cls)
           {//code
           }
}

我有一个错误说 mysec_cls 不是 MyClass 类型。正如我意识到的那样,指针指向第一个 if 并且永远不会指向 else。

.h error: no match for operator= in *s1 = obj. 
note: candidates are: MyClass& MyClass::operator=(const MyClass&)

如果在 test_header.cpp 我只有一个 if 和 if 在模板中我只有一个来自 test_header 中的 if 的引用,但如果我对 T& obj 有多个引用,我没有这个错误我有错误我已经提到了。

为什么?如何改变这个?我正在使用 g++ 编译。

【问题讨论】:

  • 你能修复你的代码 sn-p 上的缩进吗?
  • 一个简单的重载将为您节省大量精力的明显案例。无论如何,您的代码难以理解-您需要组合一个更清晰的示例,并且您可能会得到一些答案。 ..
  • 从你的问题来看,听起来你已经删除了明显有问题的代码: //using std::type_info& and typeid i get the ype of the obj;在 std::string s 中,我保留了 obj 的名称,然后......
  • 这是什么奇怪的语法? class MyClass {} *mycls;class MySecondClass {} *MySC;?你希望通过这个实现什么目标?
  • @Nim,该语法正在创建类型 (class MyClass {}) 并创建类型为 pointer-to-newly-created-type 的变量。基本相当于class MyClass {}; class MyClass *mycls;

标签: c++


【解决方案1】:

当您实例化一个模板时,它会被完全编译,而与最终执行的代码分支无关。在您的特定代码中,即使 if 语句将确保仅执行具有有效分配的分支,也必须编译两个分支,并且其中一个不正确。

考虑简单的非模板示例:

void foo( int x ) {
   if ( true ) {
      int y = x;
   } else {
      std::string s = x;
   }
}

虽然第二个分支永远不会被执行,但编译器必须确保代码是正确的(即使它可以优化它),并且它会失败,因为您无法从整数初始化字符串。您的代码中也存在同样的问题。

至于如何解决,最简单的方法是不用编写分支,而是使用函数重载解析来解决分派到适当的代码段。这样你就可以有两个不同的函数(或者如果你想要的特殊化,但我建议使用不同的重载),每个函数只适用于其中一种类型,因此赋值是有效的。

【讨论】:

  • 您可以在旧帖子中发布此内容(删除后)。
  • 当我意识到答案错误后,我立即删除了它,我不想让任何人在我写这篇文章的同时对错误的答案感到困惑。对于大多数人来说,旧答案甚至不再出现,而对于我们这些可以看到它的人来说,它出现在列表的末尾。我认为我们对这方面有不同的观点(从我过去所见),对我来说,这不是对旧答案的修改,而是一个新的不同的答案。修改答案(而不是编辑小错误或附加信息)只会让其他人更加困惑。
  • @Nawaz:这个讨论可以进行到我们双方都想要的时间,你认为应该少发帖子,因为你不知何故觉得最后多余的灰色帖子令人不安。我认为即使要添加正确的答案也要删除不正确的答案,前提是否则附加在问题上的任何额外信息都会产生误导。这不是今天的特殊情况,但您可以回到您的答案,并找出您修改后的答案中剩下的多少 cmets 与您的答案的最终版本无关。我觉得这更令人不安
  • @David:是的。这就是我要说的。删除帖子后,您可以对其进行数千次编辑,重新编辑,一旦完成,您可以再次取消删除,以便其他人可以看到它。我认为它避免了不必要的新帖子。
  • 我同意大卫的观点。这是一个完全独立的答案,应该有一个新的发布日期,重置投票,没有 cmets。我理解重用原则,有时它很合适,但人们通过编辑完全改变问题和答案来重用问题和答案是非常令人恼火的。
【解决方案2】:

我的水晶球告诉我,你正在以某种方式变形你从 type_info 中检索到的类名,因为这个名称不是直接的类名,而是一个从类名充分派生以允许相等的实现定义的字符串比较,并且在该过程中,两个名称都映射到“MyClass”(即您正在切断内部类的名称),因此两者最终都在同一个处理程序中。

如果要在运行时比较类型,直接比较type_info节点:

if(typeid(obj) == typeid(MyClass)) ...

如果您在 method 中处理的类型的封闭列表(并且在您的实现中,有,因为您无法将更多案例添加到链接的 if 语句列表中),没有真正的理由使用一个模板;定期重载就足够了:

class MyClass
{
    std::string name;
    // ...
    class MySecondClass
    {
        std::string surname;
        // ...
    } *mysc;

    bool method(MyClass const &obj)
    {
        MyClass *copy = new MyClass;
        *copy = obj;
        // ...
    }
    bool method(MySecondClass const &obj)
    {
        MySecondClass *copy = new MySecondClass;
        *copy = obj;
        // ...
    }
    // ...
};

【讨论】:

  • 虽然 OP 使用 typeid 的方法是错误且荒谬的,但它不是错误的根源,因为代码无法编译并且 typeid 是运行时的事情。
  • +1,因为这代码最初应该看起来的样子。
  • ...哦,MyClass *copy = new MyClass(obj) 也会这样做。
  • 我不知道如何解决我编辑代码时出现的错误。需要一些帮助:)
  • 正如@jan 所说, typeid 在这里是错误的方法,我提到它主要是为了完整性。阅读我的其余答案。
猜你喜欢
  • 1970-01-01
  • 2019-07-30
  • 1970-01-01
  • 1970-01-01
  • 2011-05-30
  • 1970-01-01
  • 2012-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多