2011-08-31 76 views
5

在“C++程序设计语言”预定义的含义,在265页中,作者提出了以下声明:问题对运营商

由于历史的偶然的,运营商=(转让),&(地址 - ),和(排序; 第6.2.2节)在应用于类对象时具有预定义的含义。这些预定义的意义可以 通过使他们的私人而不能接触到一般用户:

那么下面的例子说明:

class X { 
private: 
void operator=(const X&); 
void operator&(); 
void operator,(const X&); 
// ... 
}; 

void f(X a, X b) 
{ 
    a = b; // error: operator= private 
    &a;  // error: operator& private 
    a,b; // error: operator, private 
} 

我不是很了解做这些“错误”意见指至?这是否意味着我不应该这样定义一个函数f,或者所有的=&,并且,运营商应按照默认方式来使用,没有必要重新定义它们呢?

回答

8

这个例子简单显示了一种方法,以防止自己或由使用运算符,它可以在不具有类定义中使用的代码的其他开发人员,因为它们会自动产生(并且具有用于操作默认含义它们代表)。

意味着,如果你尝试分配ba(符合a = b),它会导致一个错误,因为赋值运算符是在类定义私有的例子的作者。在地址中的第二行中,并且在第三逗号操作符的情况下发生

类似的错误。

如果你知道它们不应该被使用(或尚未实现),那么使默认的操作符/构造函数是私有的是好的,因为可能会意外地使用非常频繁的操作符,如赋值或复制构造函数,不知道它的默认行为与类生命周期冲突。如果这样的操作符或构造函数在类设计的最初阶段被设置为私有的,编译器将生成编译时错误,而不是在程序员意外地使用该方法的情况下执行潜在危险的操作,恕不另行通知。

认为默认的赋值操作符和成员指针:它会复制指针,而你可能希望对象是数据的所有者。然后,在某人将一个对象分配给另一个对象而不知道该分配未实现之后,最终会出现双重空闲错误。相反,如果操作员是私人的,你会得到一个很好的错误,代码甚至不会编译,你会知道发生了什么。

1

提供您自己的任何操作符实现与实现类方法基本相同。操作员和方法在可访问性方面相同。你所做的是禁止从调用者的代码访问操作员。

,如果你定义的私有方法,然后试图从一些代码,是不是你的类的一部分调用它这绝对是一样的。只要让操作员公开,错误就会消失。

1

它基本上防止从制造“X”对象并使用“=”,“&”,和“”操作员在该类的任何一个。因为这个类的作者可能实现这些对象的含义与该类的消费者可能认为它们的含义完全不同......所以最好在含糊不清的情况下尽量防止它们被使用。

1

函数f是用户尝试使用私有操作符的示例。它通过使它们变为私密来向你显示你正在阻止的代码。注释// error意味着包含该行的程序将因指定的原因而无法编译。

5

作者打算在这里指出,运营商=,&,通常隐含可用于类。
所以,如果你不希望你的物体通过它们进行操作,那么你声明它们为private,从而不允许它们的使用。

由于它们被声明为private,所以你不能在类之外访问它们,并且编译器会给你一个编译错误。该功能就是一个例子。

+0

我发现这个答案比最上面的一个更清晰:*预定义的含义*的意义在于它们存在并且将在默认情况下工作,并且*禁止*在C++ 03中的行为的唯一方法是通过声明它们为'private'(C++ 0x添加'delete'关键字) –

0

在讨论错误之前,这里的一个关键是要明白这些操作会隐式提供给您的班级。这是Scott Meyers的建议“知道C++默默地编写和调用什么函数”的精髓。

C++将自动为您的类实现赋值运算符,但可能无法正确执行(例如,如果您的类包含指针成员变量)。通过明确定义赋值运算符,您告诉编译器使用您的实现,而不是为您生成一个。并且通过将它私有化,你基本上不允许将一个类实例分配给另一个类实例。任何你试图在你的代码中执行此操作的地方,编译器都会抱怨,如果你不想分配,这是一件好事。

在函数f中,作者向您展示了这些语句不会编译,因为操作符是如何在类中定义的。为你的类重新定义运算符是完全可以接受的,有时它也是必须的(例如,在你的类中实现一个指针成员变量的深层副本)。这个例子的要点是要证明:a)你可以为你的类提供你自己的这些运算符的实现,以及b)因此你可以控制运算符是否被正确支持和实现。