Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;模板和子类? 爪哇学习C++,我知道了在C++中如何做,但不是C++。_C++_Oop_Interface - Fatal编程技术网

C++;模板和子类? 爪哇学习C++,我知道了在C++中如何做,但不是C++。

C++;模板和子类? 爪哇学习C++,我知道了在C++中如何做,但不是C++。,c++,oop,interface,C++,Oop,Interface,我有一个容器对象的模板,定义如下: template <class T> class Container { vector<T> contained; public: void add(T givenObject) { this->contained.push_back(givenObject); } T get(string givenIdentifier) throw (exception) {

我有一个容器对象的模板,定义如下:

template <class T>
class Container {
    vector<T> contained;

    public:

    void add(T givenObject) {
        this->contained.push_back(givenObject);
    }

    T get(string givenIdentifier) throw (exception) {
        for (int i = 0; i < this->contained.size(); i++) {
            if (this->contained[i].getIdentifier() == givenIdentifier) {
                return this->contained[i];
            }
        }
        throw new exception("An error has occured which has caused the object you requested to not be found. Please report this bug.");
    }

    bool empty() {
        return this->contained.empty();
    }

    bool identifierExists(string givenIdentifier) {
        for (int i = 0; i < this->contained.size(); i++) {
            if (this->contained[i].getIdentifier() == givenIdentifier) {
                return true;
            }
        }
        return false;
    }
};
在Java中,当声明泛型(模板)时,可以定义一个超类/接口,T的所有成员都必须扩展该超类/接口,以避免产生错误。然而,我不确定在C++中有这样的方法,我的担心是将实现与一个可能不被定义的GISTIONER方法耦合在一起是一个坏的设计。p> 现在,如果是这样的话,这不是什么大问题,这只是一个帮助我学习语言的小挑战项目,但我喜欢尝试做正确的事情。有没有办法做到我所想的?我知道你可以用原语来做,例如:

template <int T>
模板

是有效的,但当我尝试使用用户定义的类时,会出现编译器错误。有什么建议吗?

你什么都不用做。如果
contained[i]
没有
getIdentifer()
函数,您将得到一个编译时错误(就像您在Java中使用接口相反一样,就像您在使用模板之外一样)

详细说明:如果你要写

 int x = 10;
 long id = x.getIdentifer();

这将被视为“糟糕的设计”。这只是一个错误,编译器会发现。这正是在您的示例中会发生的情况。

您不可能人为地限制模板类型参数。如果给定的类型不支持您使用它的方式,您将收到一个编译器错误。一个被称为“概念”的特性将被添加到下一个C++标准中,但是由于时间限制,它被推迟到下一个标准。如果T没有可见的
getIdentifier()
函数,则不会编译实例化


模板参数需要在编译时推导<代码>模板有效,因为第一个模板参数是整数;您可以用任何常量整数实例化它。如果试图将其与非常量整数变量一起使用,则无法编译。类的实例不是编译时常量,因此不能使用。

C++在编译时多态性(即模板)和运行时多态性(即继承)之间划出了一条非常明显的界线。因此,该语言不支持您要执行的操作

一个典型的做法是,除了T之外,还提供一个可以获取给定T标识符的类型。这将两种行为解耦为两种类型,并且可以指定(用英语)必须实现的接口

template <class T, class StringIdForT>
class Container 
{
  ...
   bool identifierExists(string givenIdentifier) 
   {
        StringIdForT idGetter;
        for (int i = 0; i < this->contained.size(); i++) 
        {
            if (idGetter.getIdentifier(this->contained[i]) == givenIdentifier) 
            {
                return true;
            }
        }
        return false;
   }  
};
模板
类容器
{
...
布尔标识符存在(字符串给定标识符)
{
斯特林格特;
对于(inti=0;icontained.size();i++)
{
if(idGetter.getIdentifier(this->contained[i])==givenIdentifier)
{
返回true;
}
}
返回false;
}  
};

你有一个类似的问题,StringIdForT仍然必须定义一个指定的方法

你已经得到了另外两个答案,都很好(特别是@Daupic's,IMO)。我要补充的是,您给出的代码看起来非常像是对
std::map
的低效模仿。在大多数情况下,
std::map
可能工作得更好。如果您查看它的接口,它还将向您展示一种方法,使您的容器不必直接指定
getIdentifier()
,而不是直接使用类似
getIdentifier()
,它使用一个默认为
std::less
的比较函子,这将(反过来)使用<代码>::操作程序,因为您已经得到了完美的答案,一个次要指针:在C++中,对象不是自动引用的,就像java一样。使用
get(const-string&givenIdentifier)
而不是
get(string-givenIdentifier)
避免复制,同样在identifierExists()Cubbi中,感谢您的提示。我一直在做的,不是在方法签名中请求引用,而是在启动时简单地传递一个指向函数的指针。然而,对于长期使用,要求在方法中引用可能是一个更好的选择,因为这一事实澄清了该方法真正要求的是什么;这是一个很棒的回应,对于我来说,仍然是一个非常有用的人,因为他仍然在试图去收集复杂的C++。我真的很感激这些信息,在实际的生产产品中,我会考虑使用Std::map,尽管在这种情况下,我觉得实现将足以满足基本上是一种心理练习的需要。说真的,谢谢你的帮助。
template <class T, class StringIdForT>
class Container 
{
  ...
   bool identifierExists(string givenIdentifier) 
   {
        StringIdForT idGetter;
        for (int i = 0; i < this->contained.size(); i++) 
        {
            if (idGetter.getIdentifier(this->contained[i]) == givenIdentifier) 
            {
                return true;
            }
        }
        return false;
   }  
};