【问题标题】:C++ How do I inherit from a template class, to a template class, with the same argumentsC++ 如何从模板类继承到具有相同参数的模板类
【发布时间】:2015-08-23 19:17:26
【问题描述】:

这个问题已经有了答案here除了,因为我读了这个问题但仍然无法弄清楚哪里出了问题。编辑:不,这个错误的原因并不不同。

我正在尝试这样做:

template<typename T>
class base
{

protected:

    base() {}

    virtual ~base() {}

    virtual void method(void* const voidp) const = 0;

};

template<typename T>
class child : public base<T> // ERROR: child is not a template type
{

public:

    child(std::vector<T> arg)
        : _arg{arg}
    {
    }

    virtual ~child() {}

    void method(void* const voidp) const
    {
        for(template std::vector<T>::const_iterator it = _arg.begin(); it != _arg.end(); ++ it)
        {
            method2(voidp, *it);
        }
    }

protected:

    std::vector<T> _arg;

};

我有点困惑,因为这似乎与链接的示例相同,除非我弄错了?

编辑:这是method2

void method2(void* const voidp, const double& arg) // second argument comes in both double and float formats
{
}

// so there is also a: void method2(void* const voidp, const float& arg)

【问题讨论】:

  • std::vector&lt;T&gt;::iterator应该是typename std::vector&lt;T&gt;::const_iterator,而里面的method(voidp, *it);调用是错误的——没有这个函数
  • @PiotrSkotnicki 抱歉,这是个错误,让我改一下。我的最小示例的问题是我把它搞砸了,只给了你一半。
  • child的构造函数有一个sintax错误:_arg{arg}应该是_arg(arg)
  • @enzom83 没有语法错误 - 这是 C++ 11

标签: c++ oop templates c++11 inheritance


【解决方案1】:

不知道你为什么会看到

"// 错误:child 不是模板类型"

但是,您缺少的一件明显的事情是typenamestd::vector&lt;T&gt;::iterator it 之前

也应该是const_iterator

for(typename std::vector<T>::const_iterator it = _arg.begin(); 
     it != _arg.end(); 
      ++it)
{
    //method(voidp, *it); //<--- Assuming you've this somewhere not shown in current post
}

【讨论】:

  • 我不认为这是问题所在...为什么在迭代器之前有 typename?
  • 因为std::vector&lt;T&gt;::const_iterator 是依赖类型名称。此外,如果您认为这不是当前帖子的问题,您还必须提供 SSCCE
  • @user3728501 好吧,看看this,现在按告知修复
【解决方案2】:

如果您遇到与我相同的问题,可能是您在代码的其他地方定义了friend class?在具有不同编译器和编译器选项的不同系统上使用我的代码后,我侥幸将其编译。我相信这是因为在某个时候我从项目的文件中删除了一行,并且在检查这个文件时,我认为它曾经有一个朋友类定义。我假设这导致编译器认为我没有编写模板类?虽然我并不完全相信这就是原因。

【讨论】:

    【解决方案3】:

    这个错误没有可能的原因,除非可能有一个没有类模板的类child 预先声明。

    一个原因可能是您应该使用() 而不是{} 来初始化成员:

    child(std::vector<T> arg)
            : _arg{arg}
        {
        }
    

    应更正为:

    child(std::vector<T> arg)
            : _arg(arg)
        {
        }
    

    通过 const 引用也更好:

    child(const std::vector<T>& arg)
            : _arg(arg)
        {
        }
    

    但是,还有一些其他方面可以改进以帮助该计划:


    for 循环不会编译:

    for(std::vector<T>::iterator it = _arg.begin(); it != _arg.end(); ++ it)
        {
            method2(voidp, *it);
        }
    

    T 是一个从属名称,这意味着应将 std::vector&lt;T&gt;::iterator 更正为 typename std::vector&lt;T&gt;::iterator。你可以阅读更多关于这个here的信息。

    但是,std::vector&lt;T&gt;::iterator 也应更正为 std::vector&lt;T&gt;::const_iterator。由于函数methodconstconst 表示该函数将承诺不修改类的任何 成员。但是,向量中的 iterator begin() 函数不是 const 限定的,这意味着编译器不知道您是否要修改成员。因此,必须使用重载const_iterator begin() const,以便编译器明确知道您不会修改任何成员。

    另一个注意事项:如果你使用c++11,你可以通过使用 range-for 循环来缩短循环:

    for(const auto& x : _arg)
    {
        method2(voidp, x);
    }
    

    在类中不需要两次声明public:;一旦 public 被声明一次,后面的所有内容都将是公开的,直到编译器到达另一个 protected/private 关键字,反之亦然。

    请注意,class 的默认访问级别为 privatestruct 的默认访问级别为 public。因此,您的课程可以稍微修改为:

    template<typename T>
    class child : public base<T>
    {
    public:
        child(const std::vector<T>& arg)
            : _arg(arg)
        {
        }
    
        virtual ~child() {}
    
        void method(const void* voidp) const
        {
            for(typename std::vector<T>::const_iterator it = _arg.begin(); it != _arg.end(); ++ it)
            {
                method2(voidp, *it);
            }
        }
    
    protected:
        std::vector<T> _arg;
    };
    

    base 课程也是如此:

    template<typename T>
    class base
    {
    protected:
        base() {}
        virtual ~base() {}
        virtual void method(const void* voidp) const = 0;
    };
    

    与您在函数声明中放置 const 关键字的位置保持一致:

    你有:void* const voidp,然后是const double&amp; arg。如图所示,const 关键字的放置不一致 - 一个在类型之后,一个在类型之前:

    为了保持一致性,最好使用const void* voidp, const double&amp; argvoid* const voidp, double const&amp; arg


    最后,我使用 MSVC 编译了以下代码,它运行良好:

    template<typename T>
        class base
        {
        protected:
            base() {}
            virtual ~base() {}
            virtual void method(const void* voidp) const = 0;
        };
    
    template<typename T>
        class child : public base<T>
        {
        public:
            child(const std::vector<T>& arg)
                : _arg(arg)
            {
            }
    
            virtual ~child() {}
    
            void method(const void* voidp) const
            {
                for(typename std::vector<T>::const_iterator it = _arg.begin(); it != _arg.end(); ++it)
                {
                    method2(voidp, *it);
                }
            }
    
        protected:
            std::vector<T> _arg;
        };
    

    希望这会有所帮助:)

    【讨论】:

    • 评论您的一些观点:为什么我应该用 () 而不是 {} 进行初始化?
    • 更多 cmets:是的,我快速复制并粘贴了它,所以它应该是 const_iterator,对于公共/私有标签也是如此,并且也是 for 循环中的模板 - 我已经修改了示例以解决这个问题,这些不是这里的主要问题
    • 最后我不相信“自动”所以我选择不使用它......我不喜欢那种马虎的编程方式......
    • 哦,我看不到const 的问题?这是什么地方?
    • @user3728501 - const 问题本身并不是一个大问题;这只是为了您的代码的一致性。因为最好在类型之前或之后不断地放置 const 以使代码更加一致。
    猜你喜欢
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多