C++重载getter两次,一次返回指针,另一次返回常量引用,都失败了
C++ overloading getter twice, one returning pointer and the other const reference, fails
正如标题所说,我试图重载getter,以向成员变量返回指针(mutator方法)和常量引用(inspector方法)。
请注意,上面链接中的示例使用了引用和常量引用,我不希望这样。
#include <vector>
class A {
public:
A() : v() {}
const std::vector<int>& get_v() const {return v;}
std::vector<int>* get_v() {return &v;}
private:
std::vector<int> v;
};
int main() {
A a;
a.get_v()->size(); // ok
a.get_v().size(); // error: request for member ‘size’ in ‘a.A::get_v()’,
// which is of pointer type ‘std::vector<int>*’
// (maybe you meant to use ‘->’ ?)
}
在我尝试使用它抛出上面给出的错误描述之前,它似乎还可以工作。这种不当行为有原因(和解决办法)吗?
在我尝试使用它抛出上面给出的错误描述之前,它似乎还可以工作。
a.get_v().size();
该代码显然是错误的,因为std::vector<int>* get_v()
返回了一个指针。关于试图访问指针的成员,错误消息非常清楚,这是你不能做的。要修复它,你需要使用箭头运算符来取消引用指针,就像在上面一行所做的那样。
你怎么能说出用了哪一个?
一个重载是非常数,并且只能在非常数对象上调用。另一个是const,可以对const和非常量对象调用,但永远不会对非常量对象进行调用,因为非常量重载是首选。它是首选,因为它不需要将非常量对象参数转换为常量。对const成员函数的调用将需要这样的转换。与那些需要转换的重载相比,不需要转换参数的重载更受欢迎。因此,总是为非常量对象参数调用非常量版本。
下面的也失败了
std::vector<int>& v = a.get_v();
a
仍然是非常数,因此选择了返回指针的重载。不能将非指针引用绑定到指针。
如果你想调用在非常量对象上返回常量引用的函数,那么你必须给它另一个名称,这样它就不会有首选的重载。
你有这方面的参考资料吗?
我将引用cppreference.com,因为这是非常基本的东西——尽管规则有点复杂。如果你怀疑这个标准的正确性,就查一下。
首先,关于成员函数重载的一些信息:
如果任何候选函数是成员函数(静态或非静态),但不是构造函数,则将其视为具有一个额外的参数(隐式对象参数),该参数表示调用它们的对象,并出现在第一个实际参数之前。
我认为很明显,两个重载都是候选者,因为它们有相同的名称。它们也是可行的,因为它们有正确数量的论据,并且是可转换的。那么,哪种过载是首选?
对于每对可行函数F1和F2,对从第i个参数到第i个自变量的隐式转换序列进行排序,以确定哪一个是更好的
如果F1的所有变元的隐式转换不比F2的所有变位的隐式转化差,则F1被确定为比F2更好的函数,并且
1) 至少有一个F1自变量的隐式转换比F2 自变量的相应隐式转换好
好的,所以更好的转换序列是优选的。。。哪个更好?让我们先弄清楚转换序列是什么。唯一的参数是隐式对象参数。传递的参数的类型为非常量A
。
作为非常数的重载有一个类型为非常数A
的隐式对象参数(它在这里并不真正相关,但在实践中它是作为指针传递的)。非常量A
不需要转换为非常量A
,因为它是完全匹配的。这将被视为身份转换。
常量重载具有类型为const A
的隐式对象参数。可以将CCD_ 8隐式地转换为CCD_。
这两个转换级别相同。在这种情况下,需要通过一长串规则。这些都不适用,直到最后一部分:
f) 或者,如果不是这样,S1和S2仅在资格转换上不同,并且S1的结果的cv资格是S2 的结果的cv资格的子集
标识转换是常量转换的一个子集。所以更好。我认为身份可能也更好,因为在计算身份转换时,cv转换需要两次转换。。。不过,我找不到关于这方面的规则。
A a
不是常量,因此编译器无法应用const std::vector<int>& get_v() const {return v;}
这项工作:
#include <vector>
class A {
public:
A() : v() {}
const std::vector<int>& get_v() const {return v;}
std::vector<int>* get_v() {return &v;}
private:
std::vector<int> v;
};
int main() {
A a;
a.get_v()->size(); // ok
const A b;
b.get_v().size(); // ok
}
编辑-添加解释
b.get_v()->size();
为什么失败?
从那里:
最佳可行功能
对于每对可行函数F1和F2,对从第i个参数到第i个自变量的隐式转换序列进行排序,以确定哪一个更好[…]
1) 至少有一个F1自变量的隐式转换比F2 自变量的相应隐式转换好
案例1:const std::vector<int>& get_v() const {return v;}
我们不需要转换任何
案例2:std::vector<int>* get_v() {return &v;}
我们需要将指针this
从const A
转换为A
——我们不能隐式执行,只能使用const_cast
所以编译器选择了情况1。
- 我是否需要在下一次转移时将所有权*转移回转移队列
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 在C++中一次将矢量值写入多个文件
- 循环中的条件:为什么每次都调用strlen(),而vector.size()只调用一次
- 为什么 zlib 放气初始化调用一次不起作用?
- 在一次迭代中从 txt 文件中读取多行
- 为什么无论你输入什么,这"while(cin.get(str,3))"只运行一次?
- 从子菜单返回后,正确的输入至少进入验证循环一次
- 如何在返回一次数据后从类实例中删除数据
- 递归:一次返回
- C++不止一次返回
- 如何使用C++单一实例返回仅初始化一次的对象
- C++重载getter两次,一次返回指针,另一次返回常量引用,都失败了
- 如何在c++中一次又一次地从函数返回
- 如何使用数据类型的一次返回来返回错误
- 如何写函数整洁?考虑到log,一次返回,不再缩进
- 为什么popn()一次又一次调用返回相同的输出
- Std::istringstream.good()比预期多返回一次true
- "Peek ahead"检查下一次对getline(file,line)的调用是否会返回false - 而不实际调用它,即不消耗该行
- C++跟踪一个项目一次,然后返回