【问题标题】:Return inner-class from a inherited virtual template class in C++从 C++ 中继承的虚拟模板类返回内部类
【发布时间】:2013-06-13 10:41:10
【问题描述】:

Derived<T> 继承自 Base<T>Derived<T>::m 应该返回一个 Derived<T>::Inner 对象。什么错误,我不明白。

考虑以下代码:

template <typename T>
class Base {
public:
    class Inner {
    public:
        virtual void x() = 0;
    };
    virtual Inner m(std::string arg) = 0;
};

template <typename U>
class Derived : Base<U> {
public:

    class Inner : Base<U>::Inner {
    public:
        virtual void x();
    };
    virtual Inner m(std::string arg);
};

template <typename U>
Derived<U>::Inner Derived<U>::m(std::string arg) {
    std::cout << "calling Derived::m() " << arg << std::endl;
    return new Inner();
}

template <typename U>
void Derived<U>::Inner::x() {
    std::cout << "calling x" << std::endl;
}

Derived<std::string>* d = new Derived<std::string>();
Derived<std::string>::Inner* inner = d->m("test");
inner->x();

我收到以下错误:

invalid covariant return type for 
   'Derived<U>::Inner Derived<U>::m(std::string) [with U = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]'
overriding 'Base<T>::Inner Base<T>::m(std::string) [with T = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]'

【问题讨论】:

    标签: c++ inner-classes class-template


    【解决方案1】:

    您尝试根据返回类型覆盖函数。 Base::Inner 类与Derived::Inner 不同,因此不能从派生类覆盖基类中的m 方法。

    Derived 类中的m 方法需要返回Base::Inner。但是,这将导致 object slicing 所以你不能直接这样做。相反,您必须返回引用或指针。

    我建议后者,使用std::unique_ptr

    可能是这样的:

    template<typename U>
    class Base
    {
    public:
        class Inner { ... };
    
        using inner_ptr = std::unique_ptr<Base<U>::Inner>;
    
        virtual inner_ptr m(const std::string&) = 0;
    };
    
    template<typename U>
    class Derived : public Base<U>
    {
    public:
        Base<U>::inner_ptr m(const std::string&);
    
        class LocalInner : public Base<U>::Inner { ... };
    };
    
    template<typename U>
    inline Base<U>::inner_ptr m(const std::string& arg)
    {
        return Base<U>::inner_ptr(new LocalInner);
    }
    

    【讨论】:

    • 为什么不std::unique_ptr?除非明确需要共享,否则这应该是默认设置。
    • @TemplateRex:是的,是的,成千上万的是的! :D
    • @MatthieuM。大声笑,它引发了宠物的烦恼吗?
    • @TemplateRex:我厌倦了一遍又一遍地重复这一点,太多人认为shared_ptr 是一种不干涉的方法,就像它是一个 GC 或其他东西,并且忘记了这些问题周期数。
    • 谢谢!但是调用Derived&lt;std::string&gt;* d = new Derived&lt;std::string&gt;(); 会导致错误:error: dependent-name 'Base&lt;U&gt;::inner_ptr' is parsed as a non-type, but instantiation yields a type。稍微改变了方法:template&lt;typename U&gt; inline typename Base&lt;U&gt;::inner_ptr Derived&lt;U&gt;::m(const std::string&amp; arg) { return Base&lt;U&gt;::inner_ptr(new Derived&lt;U&gt;::LocalInner()); }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    相关资源
    最近更新 更多