基于C ++的强制编译时错误,该错误基于调用构造函数的情况

时间:2018-08-17 14:28:41

标签: c++ compiler-errors runtime

在我的C ++类中,我想防止某些成员函数能够被调用,具体取决于使用哪个构造函数创建对象,并且如果尝试这样做,则会导致编译时错误。

一些上下文:

我的项目中已有一个广泛使用的类,该类用于读取/写入数据库。有时,当我创建此类的实例时,我只想从数据库中读取数据,因此,我想创建一个新的构造函数,该构造函数是一个“只读”构造函数,可防止所有写入数据库的函数从做任何事情。 (我这样做的原因是,如果对象要向其写入数据,我想从被访问的数据库中“锁定”该行,但是如果该对象仅从数据库中读取,则不这样做。)

当然,要防止成员函数在运行时基于使用哪个构造函数执行任何操作,这并不是很困难。例如:

class DatabaseInterface
{
   private:

      bool readOnly;

   public:

      // Constructor #1
      // This constructor allows read only from database
      DatabaseInterface(int x)
      {
         readOnly = true;

         // Do something
      }

      // Constructor #2
      // This constructor allows read/write to database
      DatabaseInterface(int x, bool y)
      {
         readOnly = false;

         // Do something
      }

      void UpdateDatabase()
      {
         if (readOnly) return;

         // Update Database
      }
};

通过此类,您可以执行以下操作:

DatabaseInterface A(5);
DatabaseInterface B(5,true);
A.UpdateDatabase();           // Does nothing
B.UpdateDatabase();           // Updates database

但是有没有办法修改此类,使得上面的A.UpdateDatabase()会导致编译时错误?

我的想法是(由于类的所有实例当前都使用带有一个参数的构造函数),如果我可以为此强制执行编译时错误,那么我可以确保该类的所有实例都将使用正确的构造函数,因为如果试图在使用“只读”构造函数创建的对象上使用“书写”功能,它甚至都不会编译。

我想知道这是否可行,因为请注意,只要它是bool类型,构造函数中第二个参数的 value 都无关紧要。

3 个答案:

答案 0 :(得分:3)

如果您愿意将类作为模板,则可以使用标签来创建只读的DatabaseInterface或读写的DatabaseInterface。看起来像

struct read_only_t{};
struct read_write_t{};

template<typename T>
class DatabaseInterface
{
   public:
      DatabaseInterface(int x)
      {
         // Do something
      }

      void UpdateDatabase()
      {
         static_assert(!std::is_same_v<T, read_only_t>, "DatabaseInterface is in read only mode");
         // Update Database
      }
};

现在,如果您尝试在UpdateDatabase上调用DatabaseInterface<read_only_t>

,则会收到一个不错的编译器错误。

答案 1 :(得分:1)

是的,只要愿意为DatabaseInterface类创建模板,就可以使它在编译时失败。

例如,您需要添加bool类型的模板参数,然后仅将UpdateDatabase()函数专用于<true>的模板参数值。当您尝试在参数为UpdateDatabase()的对象上调用<false>函数时,编译器会抱怨该函数已声明,但未定义。

答案 2 :(得分:1)

您可以为此使用继承:

class ReadOnlyDBI {
public:
    void readData();
    virtual ~ReadOnlyDBI();
};

class ReadWriteDBI : public ReadOnlyDBI {
public:
    void writeData();
};


void someFunctionReadingData( ReadOnlyDBI &dbi )
{
    dbi.readData(); // fine
    dbi.writeData(); // error, this function can only read
}

void foo()
{
   ReadWriteDBI rwd;
   rwd.readData(); // fine to read from it
   someFunctionReadingData( rwd ); // we can pass it to a func that reads 
   rwd.writeData(); // we can write
}

否则,您还必须写someFunctionReadingData作为模板。