【问题标题】:Can I declare a different typedef depending on class?我可以根据类声明不同的 typedef 吗?
【发布时间】:2016-06-29 00:29:38
【问题描述】:

是否可以根据实例化的派生类有不同的类型定义?

假设我有一个父类,它有一个虚函数 func()、两个 int 成员和一个 myType 类型的向量,以及两个共享相同 int 成员和向量的子类,但它们的实现是 @ 987654323@ 要求 myType 略有不同。

例如:

class Parent {
  protected:
    int myMember;
    int myOtherMember;
    std::vector<myType> vec;

  public:
    Parent(variable);
    virtual int func() = 0;
}

class Child1 : public Parent {
  private:
    typedef <some type definiton> myType;

  public:
    Child1(variable) : Parent(variable){};
    int func() {return someFunc();};
}

class Child2 : public Parent {
  private:
    typedef <some other type definiton> myType;

  public:
    Child2(variable) : Parent(variable){};
    int func() {return someOtherFunc();};
}

我可以这样做吗?当我尝试过它时,它会在头文件中创建一个循环依赖,因为首先需要包含类Parent,但随后需要定义myType

有没有办法根据班级向前声明myType?还是我只需要在每个类中包含一个不同的myType 向量,如下所示:

class Parent {
  protected:
    int myMember;
    int myOtherMember;

  public:
    Parent(variable);
    virtual int func() = 0;
}

class Child1 : public Parent {
  private:
    typedef <some type definiton> myType;
    std::vector<myType> vec;

  public:
    Child1(variable) : Parent(variable){};
    int func() {return someFunc();};
}

class Child2 : public Parent {
  private:
    typedef <some other type definiton> myType;
    std::vector<myType> vec;     

  public:
    Child2(variable) : Parent(variable){};
    int func() {return someOtherFunc();};
}

【问题讨论】:

  • 让它成为你父类的模板参数。
  • 啊,谢谢,我完全忘记了模板,自从我用 c++ 做任何事情以来已经有几年了,我慢慢地记住了这一切..

标签: c++ typedef forward-declaration


【解决方案1】:

这是templateman 的工作!

首先我们声明Parent

template <class TYPE>
class Parent {
  protected:
    int myMember;
    int myOtherMember;
    std::vector<TYPE> vec;

  public:
    Parent(TYPE variable);
    virtual int func() = 0;
};

不幸的是,Child1 中包含的自定义类型无法使用这种方法,因为需要先声明该类型,然后才能对其进行专门化模板。为了方便起见,我在这里使用intdouble。根据需要更换。

using Child1Type = int;
// or typedef int Child1Type; pre-C++11
class Child1 : public Parent<Child1Type> {
  public:
    Child1(Child1Type variable) : Parent(variable){};
    int func() {return someFunc();};
};

using Child2Type = double;
class Child2 : public Parent<Child2Type> {

  public:
    Child2(Child2Type variable) : Parent(variable){};
    int func() {return someOtherFunc();};
};

编辑

因为没有早点得到这个而自责(并且因为我知道这是可能的,但我的想法是错误的,所以浪费了太多时间)

在 Parent 中声明类型。根据需要查看类型的人员设置访问权限。在这里,我将Type 公开以在main 中进行测试。该类型在Parent 中声明,并且对子项可见(并且通过因为它是public)子项可见。

还去掉了所有不需要的东西,并使用了固定宽度的整数类型,这样我就可以很容易地展示它们之间的区别。

我认为这正是 Pixelchemist 所暗示的。

template <class TYPE>
class Parent {
  public:
    using Type = TYPE; // declare Type here
  protected:
    int myMember;
    int myOtherMember;
    std::vector<Type> vec; // visible here

  public:
    Parent(Type variable); // here
    virtual ~Parent(){}
    virtual int func() = 0;
};

class Child1 : public Parent<uint16_t> { // complicated type needs to be reproduced 
                                         // only once, here in the specialization
  public:
    Child1(Type variable) : Parent(variable){};
};

class Child2 : public Parent<uint32_t> {

  public:
    Child2(Type variable) : Parent(variable){};
};

int main()
{
    // and visible way down here in main through Child1 and Child2
    std::cout << "Child 1: " << sizeof(Child1::Type) << std::endl; 
    std::cout << "Child 2: " << sizeof(Child2::Type) << std::endl;
}

输出是

Child 1: 2
Child 2: 4

【讨论】:

  • @guskenny83 如果你看到这个,我终于想出了如何完全做到你所追求的。我认为。
  • 最后一个问题,当我将父构造函数带到 parent.cpp 时,我得到parent.cpp:6:1: error: invalid use of template-name ‘Parent’ without an argument list Parent::Parent(int variable){,但是当我在头文件中定义完全相同的构造函数时,就可以了。
  • 您需要像这样声明它:template &lt;class TYPE&gt; Parent&lt;TYPE&gt;::Parent(int variable),但您很少希望将函数声明与模板类中的类声明分开,并且您几乎不想将函数放入 CPP文件。很好的解释为什么在这里:stackoverflow.com/questions/495021/…
  • 谢谢,我把函数定义留在了标题中,它工作正常!
【解决方案2】:

您可以简单地使用模板:

template<class T>
struct Base
{
  std::vector<T> v;
};

struct D1 : public Base<int>
{
  // all stuff in here comes into play when deriving from Base is already done
  // Thus, compiler cannot know any typedefs from here inside Base...
};

struct D2 : public Base<double>
{
};

您不能使用派生自基类的 typedef。请参阅CRTP refer to typedef in derived class from base class

【讨论】:

    【解决方案3】:

    这就是模板的用途:

    <template typename T>
    class Child : public Parent {
    private:
        std::vector<T> vec;
    public:
        Child(variable) : Parent(variable) {};
        int func() { return someOtherFunc(); };
    }
    

    然后Child 被声明为:

    Child<int> myChildInstance(10);
    

    【讨论】:

    • 我仍然对我的 typedef 去向感到有些困惑。假设 myType 对于 Child1 和 Child2 中的每一个都相当长且令人费解?
    • 如果可能的话,我宁愿不要在 Child 类中使用 std::vector&lt;myType&gt; vec,因为在我的实际场景中,有很多这样的成员
    • @guskenny83 抱歉,我没发现 myType 是您父类的一部分。看起来你现在有一个适合你的答案
    猜你喜欢
    • 2011-09-17
    • 1970-01-01
    • 2018-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    • 2019-05-06
    相关资源
    最近更新 更多