【问题标题】:Generic class variable of a certain type某种类型的泛型类变量
【发布时间】:2013-02-27 21:46:02
【问题描述】:

在 C# 中我可以这样定义:

public interface BaseObject
{
    int GetValue();
}

public class Test<T> where T : BaseClass
{
    T BaseObject;
}

这意味着我知道我总是可以调用 BaseObject.GetValue() / BaseObject->GetValue();因为我知道baseobject有这个方法。

在 C++ 中有类似的方法吗?这样我就可以定义一个多个类可以继承的接口和一个可以利用这一点的类。

【问题讨论】:

    标签: c++ class generics types where


    【解决方案1】:

    模板,比 C# 泛型更强大(并不是说它们一定更好,只是不同而已)。

    template<class T>
    class foo
    {
    public:
        int whatever() 
        { 
            return obj.GetValue();
        }
    private:
        T obj;
    };
    

    为您使用的每个模板参数创建一个单独的类。如果您提供的模板类型会导致错误,您将在编译时知道。

    【讨论】:

    • 但我需要将 T 限制为某种类型。所以它必须是一个继承自另一个对象的对象。
    • @Deukalion:那么你可以使用 C#。 C++ 是一种具有不同语义的不同语言。我认为您需要按照您所说的去做,这只是您的看法,因为您对 C# 中的操作方式更有经验,而在 C++ 中没有经验。您仍然可以在编译时检查您的模板参数是否支持所需的接口,但不是在类型级别。
    • 我问是否有类似的方法可以产生相同的结果,而不必重现多个类。例如,如果我希望 T 成为一个基类,其中包含持有该对象的类将使用的方法,但另一个对象可以扩展该对象,这意味着该对象只需要知道它是从 BaseClass 继承的对象。
    • 就像我说的那样,我不知道这是不可能的,也许不应该是,只要有一种简单的方法就可以做到。
    • "这本质上是文本替换。"没有东西会离事实很远。重复 10,000 次,C++ 模板不是 C/C++ 宏。文本替换(宏)不能做特化,参与重载解析,宏元编程非常非常笨重。
    【解决方案2】:

    您在询问C++ 概念,这是一种指定模板参数要求的方法。它们是在 C++11 工作期间提出的,但事实证明它们足够复杂以至于没有及时完成。但他们只是被推迟了,没有被遗忘。

    与此同时,duck typing 仍然非常强大,当您传递一个没有所需接口的模板参数时,它会捕获。它只是不会整齐地报告问题。

    作为一种解决方法,检查您显示的约束的一种简单方法利用了指针转换仅在向上转换时是隐式的这一事实:

    public class Test<T> where T : BaseClass
    {
        static T* enforcement_helper = 0;
        static BaseClass* enforce_inheritance_constraint = enforcement_helper;
    
    };
    

    根据您的编译器的新程度,您可能需要将这些行放在一个特殊的成员函数中(析构函数很好,因为它几乎总是被处理)。

    但是您应该只检查约束以改进错误消息(通过在明确注释的代码部分中导致失败)。 C++ 模板是鸭子类型的,它们可以与提供所需操作的任何模板参数一起使用。不需要正式的“接口”。

    【讨论】:

      猜你喜欢
      • 2020-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-26
      • 1970-01-01
      • 1970-01-01
      • 2018-04-22
      • 1970-01-01
      相关资源
      最近更新 更多