2012-01-16 69 views
5

我有一个类没有被类的方法改变,所以我把它标记为const。我的问题是,我正在使用默认赋值运算符就像复制构造函数,以避免多个声明。但在这种情况下,赋值运算符不会自动生成,所以我得到一些编译器错误: 'operator =' function is unavailable。这看起来似乎没有真正的生活场景,其中可以实际使用const类成员(例如,你是否看到过STL代码中的任何const成员?)。当赋值运算符重载时,const类成员是否有用?

有没有什么办法解决这个问题,除去const

编辑:一些代码

class A 
{ 
public : 
    const int size; 
    A(const char* str) : size(strlen(str)) {} 
    A() : size(0) {} 
}; 


A create(const char* param) 
{ 
    return A(param); 
} 


void myMethod() 
{ 
    A a; 

    a = create("abcdef"); 
    // do something 

    a = create("xyz"); 
    // do something 
} 
+0

我将标题编辑为一些我认为更贴近你的意思的东西,并且会鼓励更多有用的答案。如果您不同意,请随时将其改回。 – Crashworks 2012-01-16 07:46:22

+0

@Crashworks谢谢! – 2012-01-16 07:53:35

回答

3

这是你的误解,这是造成这个问题:

[..]未由类

成员变量的方法改变时,通过类,赋值操作符的方法改变。包括由编译器合成的那个。如果将成员变量标记为const,则表示该变量将(不应该)在对象的生命周期中更改其值。很明显,为对象分配一个新值违反了这个说法。所以如果你确实不希望这个成员改变,那么就不要使它成为const

1

是的,你可以重写赋值运算符。

因为您使用的是默认值,编译器也会尝试复制const成员。这是非法的,因为它是const

class A 
{ 
private: 
    const int a; 
public : 
    A() : a(0) {} 
    A& operator = (const A& other) {return *this;} 
}; 

int main() 
{ 
    A a; 
    A b; 
    a = b; //this is legal if operator = is declared 
} 
+2

所以const成员的价格是你可以提供一个赋值操作符,但只有一个破坏的操作符? – UncleBens 2012-01-16 07:48:35

+1

@UncleBens为什么这是坏的?不是,它只是不修改'const'成员......这应该是有道理的,对吧? – 2012-01-16 07:50:55

+1

@UncleBens:鉴于lhs上的const成员很可能与'rhs'上的一样,因为它只在构造函数中设置,所以没有必要复制它。如果它在不同的构造函数中被初始化,那么你可能希望重新考虑你的设计! – Johnsyweb 2012-01-16 07:53:17

2

const成员是很多,很多情况下的理想选择。当然,明显的情况是值不应该也不能改变,但它也是优化和并发的重要限制 - 并非每个类型都需要或应该有一个赋值运算符。

如果成员需要赋值行为,那么变量不能是const

当值/成员不能突变或通过this突变,它更清晰,以提供可变部件的独立接口(或甚至一个亚型>组合物在更复杂的情况下):

class t_text { 
public: 
// ... 
public: 
    void setString(const std::string& p); 
private: 
    const t_text_attributes d_attributes; 
    std::string d_string; 
}; 

因此,我的建议是隐藏赋值运算符,并且使“可变块”或成员设置能够为清楚:

text.setString("TEXT"); // << Good: What you read is what happens. 
text = otherText; // << Bad: Surprise - attributes don't actually change! 
+4

优化和并发是使用'const'我能想到的最不重要的原因。我想说,让你不要去想愚蠢的事情(或者至少迫使你对抛弃常量感到有点内疚),这更加重要。 – 2012-01-16 08:11:30

+0

@Frerich也许这是我的错误,但假设使用'const'是最明显的原因。我会更新以避免混淆。 – justin 2012-01-16 08:26:33

2

您不能有const成员和支持分配,至少不是 赋值与预期的语义。在逻辑上,const是一个 promiss该成员将永远不会改变,并且任务是 (隐含地,在大多数人的头脑中)一个promiss,所有数据 成员将采取右边的成员的值 (这通常意味着改变)。这两个promisses之间有一个非常明确的冲突 。

当然,很多类型不应该支持分配开始; 对于不支持赋值的类型,声明 数据成员const没有问题。但总体而言,我发现const很多 在这里不太有用; const是合同的一部分,数据成员 通常不是班级的外部合同的一部分。 (但是很多 取决于—如果数据成员是公共的或受保护的,那么事实 ,它是不可变的可能是外部合同的一部分。和 当然,没有什么不妥表达语言结构内部类不变 , )

+1

“你不能” - 嗯,你可以,但是你必须定义一个自定义任务。例如,由X分配的逻辑上可分配的对象可以包含一个指向X的常量指针,以帮助请求X释放该对象。例如,这样的事情可能会解决现有框架带来的一些问题。指针在对象的生命周期内是不变的,并且不会作为逻辑对象状态的一部分公开。即它不会成为外部赋值状态的一部分。干杯&hth。, – 2012-01-16 11:56:53

相关问题