3

Scott Meyers 在他的《Effective C++》一书中说,

要禁止编译器自动提供的功能,请将相应的成员函数声明为私有并且不提供任何实现。然后,如果有人无意中调用了一个,他们将在链接时收到错误。

我试图编写一个示例程序来实现 Scott 试图解释的内容。即使声明了成员函数public并且没有给出实现,我也可以实现相同的目标。当我尝试从另一个对象初始化一个对象时,也发生了链接错误。所以我不明白为什么 Scott 强调需要声明成员函数private

我的示例程序写在下面:

#include <iostream>

using namespace std;

class Unique
{
   private:
      int num;

   public:
      Unique(int x)
      {
         num  = x;
      }
      Unique(const Unique &obj);

      Unique& operator =(const Unique &obj);

      void disp(void)
      {
         cout << "num = " << num << "\n";
      }
};

int main()
{
   Unique ob1(3);
   Unique ob2(ob1);

   ob1.disp();
   ob2.disp();

   return 0;
}

我收到以下链接错误:

/tmp/ccXfqSqE.o(.text+0x135): 在函数main': : undefined reference toUnique::Unique(Unique const&)' collect2: ld 返回 1 退出状态

4

3 回答 3

10

编译器错误比链接错误更清晰并且发生得更早(这在从大量源文件编译的大型项目中更为明显)。大多数时候它们也更容易阅读。将成员声明为私有会引发编译错误,因此最好不要让成员未定义以禁止它们。

正如 Baptiste 所指出的,在 C++11 中有更好的 delete 关键字可用于禁止编译器生成的成员:

class A
{
     A(constA&) = delete; // copy construction is not allowed
};
于 2011-11-19T10:13:56.800 回答
2

如果您将它们声明为私有,则编译器将在检测到有人试图调用它们时立即停止,而不管该函数是否实际定义(因为它们是不允许的)。

通过将它们声明为公共,您必须等到链接器阶段才能获得错误,因为它应该是合法调用但缺少定义。

于 2011-11-19T10:15:25.010 回答
2

Scott 试图阻止某人调用构造函数并在链接时出错。这正是您遇到的情况。在编译时发现问题比在链接时发现问题更便宜。

顺便说一句,在 C++11 中,我们知道有官方方法可以防止编译器为我们生成函数。

class Unique{
public:
    Unique() = delete;
}
于 2011-11-19T10:20:10.483 回答