禁用由c++编译器自动提供的功能

Disallow functionality automatically provided by C++ compilers

本文关键字:功能 c++ 编译器      更新时间:2023-10-16

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

要禁用编译器自动提供的功能,请声明对应的成员函数private和give no实现。如果有人不小心打了电话,他们就会在链接时得到错误。

我试着写一个示例程序来实现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): In function main': : undefined reference to Unique::Unique(Unique constate &)' collect2: ld返回1退出状态

编译器错误比链接错误更清晰,更早发生(这在从大量源文件编译的大型项目中更为明显)。大多数时候,它们也更容易阅读。将成员声明为private会引发编译错误,因此比不定义成员来禁止它们更可取。

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

class A
{
     A(constA&) = delete; // copy construction is not allowed
};

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

通过将它们声明为public,那么你必须等到链接器阶段才能得到错误,因为它应该是一个合法的调用,但是缺少定义。

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

顺便说一下,在c++ 11中,我们知道有官方的方法来防止编译器为我们生成函数。

class Unique{
public:
    Unique() = delete;
}