【问题标题】:C++ templated class and init in constructor构造函数中的 C++ 模板类和初始化
【发布时间】:2011-07-07 13:14:01
【问题描述】:

我有一个模板类,Foo:

template <class A, class B>
class Foo
{
public:
    Foo(A &aInstance);

private:
    Attr<Foo> _attr;
};

然后我有另一个名为 Attr 的模板类,它是我的 Foo 类的一个属性,它以 Foo 类本身作为模板参数。

template <class C>
class Attr
{
    class SomeType
    {
        SomeType();
        ~SomeType();
    };

    Attr(const SomeType* st);
    ~Attr();

private:
    Attr();
}

我想在构造函数中初始化 _attr(Attr 类型),将模板中的第一个参数转换为 SomeType。

Foo 构造函数实现:

template<class A, class B>
Foo<A, B>::Foo(A &aInstance):
    _attr(
        (Attr<Foo<A, B> >::SomeType *) aInstance)
{

}

这不会编译:

错误:')' 标记之前的预期主表达式

该错误是指 Foo 构造函数实现中的转换线,好像 SomeType 未被识别。

我现在有一个实例,但仍然出现同样的错误。

【问题讨论】:

  • 我已经回滚了您上次的编辑,因为这使问题(及其答案)变得荒谬。请不要那样做。至于其他编辑:这些会干扰现有答案;我没有回滚它们,但请在以后添加进一步说明,不要更改现有代码。

标签: c++ templates typedef typename class-constructors


【解决方案1】:
template<class A, class B>
Foo<A, B>::Foo():
    _attr(
        (Attr<Foo<A, B> >::SomeType *) A)
{

}

A 是一种类型,您正在尝试将其传递给构造函数。这里需要一个实例。

【讨论】:

  • 我相信这里也需要typename
【解决方案2】:

0)

(Attr<Foo<A, B> >::SomeType *) A)

此时,A 是一个类型名,即类型的名称,因此,您不能转换任何内容。

1)

另外,Foo&lt;A,B&gt; 依赖于 AB,因此,Attr&lt;Foo&lt;A, B&gt; &gt; 也是一个依赖名称。因此,你需要一个typename 来告诉编译器SomeType 是一个类型:

(typename Attr<Foo<A, B> >::SomeType *) somePointer)

2)

此外,在 C++ 中,通常更喜欢 C++-casts 而不是 C-style-casts。你会发现很多错误。另请参阅this tutorial :)

3)

另一方面:您确定需要按设计进行转换,还是应该 Attr 正好指向 Foo&lt;A, B&gt;

【讨论】:

    【解决方案3】:

    首先,Attr 类(在你的 sn-p 中)不使用 C 类型,所以你应该解释它在哪里使用,以及 C 和 SomeType 之间的关系是什么。

    第二,在这几行

    Foo<A, B>::Foo():
        _attr(
            (Attr<Foo<A, B> >::SomeType *) A)
    

    A 是一个类型而不是一个对象。如果 _attr 应该用 Foo 对象本身初始化,那么你应该传递指针 this。

    Foo<A, B>::Foo():
        _attr(
            (Attr<Foo<A, B> >::SomeType *) this)
    

    但是,此时 Foo 对象尚未构造,因此请注意 Attr 构造函数中的指针。

    【讨论】:

      【解决方案4】:

      尝试将您的构造函数更改为:

      template<class A, class B>
      Foo<A, B>::Foo(A &aInstance):
          _attr(
              (typename Attr<Foo<A, B> >::SomeType *) &aInstance) {}
      

      你会,因为你想要一个指针,需要添加一个地址运算符来获取实例对象的地址......否则aInstance将不是指针类型,而是引用类型这实际上与传递对象本身(通过引用)而不是指向对象的指针相同。

      【讨论】:

        【解决方案5】:

        这对我有用。几个 typedef 有助于更轻松地理解模板代码:

        template<class C>
        class Attr
        {
        public:
            class SomeType
            {
                SomeType();
               ~SomeType();
            };
        
            typedef typename Attr<C>::SomeType ReachIntoSomeType;
        
            Attr(const SomeType* st) { }
            ~Attr() { }
        
        private:
            Attr();
        };
        
        template <class A, class B>
        class Foo
        {
        public:
            Foo(A &aInstance) : _attr(reinterpret_cast<AttrOfFoo::ReachIntoSomeType*>(aInstance))     
            { }
        
        private:
            typedef Attr<Foo> AttrOfFoo;
            AttrOfFoo _attr;
        };
        

        【讨论】:

        • 天哪!代码完全搞砸了!第一次在SO。有人可以为我纠正吗?谢谢!
        猜你喜欢
        • 2020-05-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多