2014-09-12 12 views
6

는 다음과 같은 템플릿 클래스 고려와 ++ 템플릿 : 두 입력 'X'의 값을 수정해서는 안 '평가'기능 이후C 'const를'

template <typename T> class Function { 
public: 
    virtual float eval(const T &x, const T &y) = 0; 
}; 

와 'Y', 난 '으로 넣어 const '.

hidden overloaded virtual function 'Function<float *>::eval' declared here: type mismatch at 1st parameter 
     ('float *const &' vs 'const float *&') 
     virtual float eval(const T &x, const T &y) = 0; 

그리고 클래스 FOO1을 인스턴스화 할 수 없습니다 : 나는 g로 컴파일 할 때 그때 나는 다음과 같은 경고를 얻을 ++ 기능

class Foo1 : public Function <float*> { 
public: 
    Foo1() : Function <float*>() {} 
    virtual float eval(const float* &x, const float* &y) { ... } 
}; 

에서 파생 된 다음 클래스를 만들 수 있습니다. 컴파일러는 'eval'함수가 구현되어 있지 않다고 말합니다. 컴파일러가 행복하려면 같이해야합니다 파생 된 클래스는 다음과 같습니다

class Foo2 : public Function <float*> { 
public: 
    Foo2() : Function <float*>() {} 
    virtual float eval(float* const &x, float* const &y) { ... } 
}; 

FOO2 : eval 함수 대신 'const를 플로트 *'의 형 '플로트 *의 CONST'의 두 개의 매개 변수를 사용합니다. 즉, Foo2 :: eval은 'x'와 'y'배열의 내용을 수정할 수 있습니다. 이것은 내가 원하는 것이 아닙니다.

나는 다음과 같이 템플릿 클래스 '기능을'변경 시도 :

virtual float eval(T const &x, T const &y) = 0; 

그러나 FOO1 여전히 작동하지 않는 클래스는 클래스 FOO2 이전 경우와 같이 작동합니다.

  1. 는 그래서 템플릿 클래스 중 하나를 'const를 T & X'또는 'T의 CONST &가 X'는 파생 클래스에서 '플로트 *의 CONST & X'를 의미하는 것으로 보인다. 이 올바른지?
  2. 파생 클래스에서 'const float * & x'(또는 'const float * x')를 원한다면 템플릿 클래스 함수는 무엇이되어야합니까?

고맙습니다.

답변

1

는 템플릿 클래스에서 const T &x 또는 T const &x 중 하나가 파생 클래스에서 float* const &x 의미하는 것으로 보인다. 이 올바른지?

네, 맞습니다. 그것에 대해 생각하는 방법은 T은 항상 const입니다. 귀하의 경우에는 T이 포인터가됩니다.

파생 클래스에서 const float* &x (또는 const float* x)을 원한다면 템플릿 클래스 함수는 무엇이되어야합니까?

소리가 class Foo2 : public Function <const float*>이어야합니다.

template <typename T> class Function<T*> { 
    public: 
     virtual float eval(const T* x, const T* y) = 0; 
}; 

다른 방법으로, Function<const float*>에서 Foo2을 유도 할 수있다 :

0

탈출구는 eval에 대해 다른 서명을 사용하기로 부분적으로 포인터 유형 Function을 전문으로하는 것입니다.

8

관찰되는 동작은 표준에 관한 한 100 % 정확합니다. "상수 포인터"대 "상수 포인터"의 고전적인 예입니다.

기본 템플릿은 (구문 const T &이다 T const & 상당) "로 지칭되고 그것이 T 객체를 수정할 수있는 T 참조"는 소요 선언한다.

그런 다음 float* 유형의 템플릿 (예 : "float에 대한 포인터")을 인스턴스화합니다. 이에 따라 템플릿 매개 변수를 대체 한 후의 함수 매개 변수 유형은 실제로는 "float *에 대한 참조이므로 float * 시작 부분을 수정할 수 없습니다." 밀입국 할 방법이 없습니다 "float *이 가리키는"float을 직접 수정할 수 없습니다.

두 가지 옵션이 있습니다. 사용의 이런 종류의 Function에서 T의 유일한 사용하는 경우 그 이후 하나, 간단하게, 템플릿 인수로 const float *를 사용하는 T 당신이 정말로 원하는 :

class Foo1 : public Function <const float*> { 
public: 
    Foo1() : Function <const float*>() {} 
    virtual float eval(const float* const &x, const float* const &y) { ... } 
    // notice two `const` keywords above: one for the pointed object, one for the reference 
}; 

즉 즉, 경우에 당신을위한 옵션이 (없는 경우 float * 어딘가에 Functionconst float*이 필요합니다. 일부 유형 특성을 사용하고 eval의 매개 변수를 수정해야합니다. 다음과 같은 내용 :

template <class T> 
struct unmodifiable { 
    typedef const T &type; 
}; 

template <class T> 
struct unmodifiable<T*> { 
    typedef const T* const &type; // if you want to keep the reference 
    // or just: 
    // typedef const T *type; // if you don't want to bother with the reference for pointer types 
}; 

template <typename T> class Function { 
public: 
    virtual float eval(typename unmodifiable<T>::type x, typename unmodifiable<T>::type y) = 0; 
}; 

class Foo1 : public Function <float*> { 
public: 
    Foo1() : Function <float*>() {} 
    virtual float eval(unmodifiable<float*>::type x, unmodifiable<float*>::type y) { ... } 
    // or just spell it out exactly, based on the variant of `unmodifiable` you've chosen, e.g.: 
    // virtual float eval (const float *x, const float *y) { ... } 
};