gpt4 book ai didi

带有 'const' 的 C++ 模板

转载 作者:可可西里 更新时间:2023-11-01 17:40:29 24 4
gpt4 key购买 nike

考虑以下模板类:

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

由于“eval”函数不应修改两个输入“x”和“y”的值,因此我将它们作为“const”。然后我创建以下派生自 Function 的类

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

当我用 g++ 编译时,我收到以下警告:

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 类。编译器表示未实现函数“eval”。为了让编译器满意,派生类必须如下所示:

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

Foo2::eval 函数使用两个类型为“float * const”的参数,而不是“const float *”。换句话说,Foo2::eval 可以修改数组'x' 和'y' 的内容。这不是我想要的。

我尝试按如下方式更改模板类“Function”:

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

但是类 Foo1 仍然不起作用,类 Foo2 和以前的情况一样。

  1. 因此,模板类中的“const T &x”或“T const &x”似乎暗示派生类中的“float* const &x”。这是正确的吗?
  2. 如果我想在派生类中使用“const float* &x”(或“const float* x”),我的模板类 Function 应该是什么?

谢谢。

最佳答案

就标准而言,您观察到的行为是 100% 正确的。这是“常量指针”与“指向常量的指针”的经典示例。

您的主模板声明它采用“对 T 的引用,它不能通过它修改被引用的 T 对象”(语法是 const T & ,等同于T const &)。

然后,您使用 float* 类型实例化模板,即“指向 float 的指针”。由此可知,模板参数替换后的函数参数类型确实是“对float *的引用,无法通过它修改所引用的float *开头”。无法直接将“无法修改 float * 指向的 float”直接走私到那里。

我看到两个选项。第一,如果这种用法是 FunctionT 的唯一用法,只需使用 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) { ... }
};

关于带有 'const' 的 C++ 模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25802658/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com