2010-05-26 32 views
2

这就是我想要做的,我不能:如何在C++丢弃常量

#include <string> 
using namespace std; 
class A { 
public: 
    bool has() const { return get().length(); } 
    string& get() { /* huge code here */ return s; } 
private: 
    string s; 
}; 

我得到的错误是:

passing ‘const A’ as ‘this’ argument of 
‘std::string& A::get()’ discards qualifiers 

我明白了什么问题是,但我该如何解决它?我真的需要has()const。谢谢。

+0

只是为了提醒您,可变成员可以通过const one,s o get()const(但可能不会返回一个非const ref)是有意义的,即使它必须在那里修改巨大的代码。 – AProgrammer 2010-05-26 11:51:56

+0

有什么样的副作用? – 2010-05-26 11:52:27

+0

它明显修改s。否则,这个简单的修复就是'return s.length()'。因此,'has()'不是const。 – MSalters 2010-05-26 15:19:54

回答

6

添加的get()第二超载:

string const & get() const { return s; } 

这将A类的const类型的对象上调用。

在实践中,我更喜欢加入只有const -typed存取,然后保持完全的修改类的内部甚至避免它们完全。例如,这意味着有一个方法DoUpdateLabel(){/*do something with s*/}而不是暴露内部。这有很好的副作用,可以避免在许多情况下重复访问器。

如果你绝对必须通过存取修改,你也不想额外的const的包装,你可以使用const_cast<>

bool has() const { return const_cast<A*>(this)->get().length(); } 

然而,如果get()有副作用和has()声明const,这是否是你真正想要的行为是值得怀疑的。

+0

否; **更改** get()。我想不出为什么你要编写'a.get()+ =“abc”'的原因。 – 2010-05-26 11:32:33

+0

:-) - 完全同意 - 这正是我刚刚添加为编辑! – 2010-05-26 11:35:50

+0

我不能有两个版本的'get()',因为我的函数(在现实生活中)比较大。我不想复制代码。 – yegor256 2010-05-26 11:36:59

2

通常有constnon-const版本的相同功能。

因此,如果您的对象被称为const对象,则会调用其中一个对象,第二个 - 如果non-const发生同样的情况。

我不得不说,这种技术通常与操作员一起使用,但也适用于您当前的情况。


而且,在当前的情况下,最好的办法可能意味着具有类似于

const string& get() const { return s } 

ONLY const方法和重构所有其他代码,以便它通过不断引用返回一个字符串工作。

+0

+1:我们显然在这里是一样的信息:-) – 2010-05-26 11:34:55

+0

我不能返回'const string&',因为我稍后使用这个字符串,改变它。而且我不能有两个具有不同签名的函数,因为它们相当大。我将复制代码 – yegor256 2010-05-26 11:36:19

0
std::string get() const { return s; } 

,因为按值传递字符串,通常是价格便宜(我不记得,如果这是一个担保),我不认为你想你看的字符串在你的脚下变更生效后,修改它。

+0

'string'就是一个例子。在现实生活中,我有另一个课程和代码 – yegor256 2010-05-26 11:41:10

+0

的另一个目的。另外,由于内存(解除)分配开销,复制甚至是小字符串实际上相当昂贵。 C++ 0x移动构造函数可能会修复这个问题... – 2010-05-26 11:44:13

+0

AFAIK,GCC/libstdC++的std :: string由引用计数的缓冲区支持,并赋予其写时复制风格的行为:复制是O(1)只要引用数是1,它便宜。虽然依赖实现细节并不是一个好主意,但它也不是世界末日。 – 2010-05-31 15:54:14

0

试试这个:

const string& get() const { return s; } 

第一个常量适用于GET方法的返回类型()。返回类型是对字符串的引用。总而言之,它是一个字符串的const引用,它强制这个返回值不会被改变。

第二个const适用于该方法,使其成为一个常量方法。

2

我认为你的问题有点含糊。

您有:

bool has() const { return get().length(); } 
string& get() { /* huge code here */ return s; } 

...,需要has()const

我能想到的三种方式来解决这个问题,这取决于你实际上要做的:

最干净的办法是,has只使用const代码。如果你的/* huge code here */代码非const,但实际上并没有改变该类的逻辑值(例如计算一个缓存的内部值)考虑在涉及的数据上使用mutable

如果/* huge code here */部分非const自然,考虑重构它变成一个不同的功能并分别称之为:

using namespace std; 
class A { 
public: 
    bool has() const { return get().length(); } 
    const string& get() const { return s; } 
    void computestuff() { /* huge code here */ } 
private: 
    string s; 
}; 

A instance; 

// old client code: 
// string s = instance.get(); 
// 
// new code: 
instance.computestuff(); // non-const call 
instance.get(); // const call 
instance.has(); // const call 

最后,您还可以投的常量性远(但请记住,需要这样做几乎总是设计不良/需要重构的标志):

class A { 
public: 
    bool has() const { return const_cast<A*>(this)->get().length(); } 
    string& get() { /* huge code here */ return s; } 
private: 
    string s; 
}; 
+0

这也是我的首选*解决方案 - 尽管它看起来不像OP倾向于那个方向。 – 2010-05-26 12:07:20