нарушает ли добавление фиктивного параметра в конструкторы класса для решения неоднозначности вызова? - PullRequest
3 голосов
/ 17 июля 2010

взять следующий класс и два определения объекта:

class Rect{
 public:
  enum centimeter;
  enum meter;
  Rect(double len,double wid,enum centimeter){
   length=(len/100);
   width=(wid/100);
  }
  Rect(int len,int wid,enum meter){
   length=len;
   width=wid;
  }
  //rest of implementation
 private:
  double length;//in meters
  double width;//in meters
};
Rect obj1(10,5,Rect::centimeter());
Rect obj2(10,5,Rect::meter());

два предыдущих конструктора имеют фиктивные параметры перечисления для решения неоднозначности вызова, вызванной в случае, если эти фиктивные параметры не существуют. Теперь, несмотря на возможность использования здесь именованных конструкторов, если я настаиваю на использовании этих фиктивных параметров, нарушает ли это какое-либо правило кодирования, о котором я должен знать?

Ответы [ 5 ]

10 голосов
/ 17 июля 2010

Я думаю, что это нарушает мой вкус. Я бы написал это так:

enum Unit {
  Centimeter = 100, 
  Meter      = 1
};

Rect(int len, int wid, Unit unit) {
  length = len / (int) unit;
  width = wid / (int) unit;
}

Rect obj1(10, 5, Rect::Centimeter);
Rect obj2(10, 5, Rect::Meter);
4 голосов
/ 18 июля 2010

BOOST_STRONG_TYPEDEF может быть ответом здесь.

BOOST_STRONG_TYPEDEF( double, Meter )
BOOST_STRONG_TYPEDEF( double, Centimeters)
BOOST_STRONG_TYPEDEF( double, Furlongs)

class Rect
{
 public:
  Rect(Meter len, Meter wid) : length(len), width(wid) 
  {};

  Rect(Centimeter len, Centimeter wid) : length(len/100), width(wid/100) 
  {};
}

Rect obj1(Meter(10),Meter(5));
Rect obj1(Centimeter(10),Centimeter(5));
1 голос
/ 17 июля 2010

STL использует эту идиому для дифференциации типов итераторов вместо концепций.

1 голос
/ 17 июля 2010

Не могу сказать, что это нарушает правило, но ... его нелегко читать.

Почему вы не можете объявить

enum metrics {
  centimeter,
  meter
};

и использовать его какпараметр конструктора?Или это может быть

class Rect {
public:
  static Rect CreateWithMeters(int width, int height);
  static Rect CreateWithCentimenets(int width, int height);
}

Либо лучше, чем текущий код на мой вкус.

0 голосов
/ 18 июля 2010
Rect(int len,int wid,enum centimeter){
  length=(len/100);
  width=(wid/100);
}

В дополнение к тому, что написали другие, эта логика плоха, потому что Rect(99,99,Rect::centimeter()) равен Rect(0,0,Rect::centimeter()).

Если вы храните счетчики внутри, не предоставляйте интерфейс с сантиметрами,ни так, ни иначе.

...