Как правильно воздержаться от CS2512 - PullRequest
0 голосов
/ 24 января 2010

Пожалуйста, помогите мне решить следующую проблему:

У меня есть следующие классы:

class ChemicalElement
{
private:
    std::string _name;
    void Init(const std::string& name);
public:
    ChemicalElement(const std::string& name);
    ChemicalElement(const ChemicalElement& ce);
};

class CombinationRule
{
private:
    ChemicalElement _ce1;
    ChemicalElement _ce2;
    void Init(const ChemicalElement& ce1, const ChemicalElement& ce2);
public:
    CombinationRule(const ChemicalElement& ce1, const ChemicalElement& ce2);
    CombinationRule(const CombinationRule& rule);
};

Реализация очевидна. Я намеревался инициализировать CombinationRule, используя метод Init, чтобы минимизировать дублирование кода. Увы, если я не использую «список инициализации элементов» в каждом конструкторе, компилятор выдает сообщение «ошибка C2512:« ChemicalElement »: не доступен соответствующий конструктор по умолчанию». Есть ли элегантный способ решить эту ошибку вместо использования конструктора по умолчанию или списка инициализации члена? Кстати: если есть какие-то другие проблемы в определении классов, пожалуйста, добавьте их тоже. Поскольку я снова посещаю C ++, я хочу знать о них.

Ответы [ 4 ]

3 голосов
/ 24 января 2010

Вы должны реализовать конструкторы CombinationRule следующим образом, чтобы они использовали соответствующие конструкторы ChemicalElement:

CombinationRule::CombinationRule(const ChemicalElement& ce1, 
  const ChemicalElement& ce2) : _ce1(ce1), _ce2(ce2) 
{ 
  ... 
}

CombinationRule::CombinationRule(const CombinationRule& rule) : 
  _ce1( rule._ce1 ), _ce2( rule._ce2 )
{
  ...
}
1 голос
/ 24 января 2010

В этом конкретном примере я бы продолжил дублирование (это просто написание двух инициализаторов, в которых нет ничего одержимого).

Но если предположить, что реальная история более сложна: используйте OO-средства, чтобы избежать дублирования кода.

class CombinationRule : public ElementPair ...

или

class Combination { ElementPair twoElements; ...}

Где ElementPair содержит два ChemicalElements и один конструктор (с общим кодом), а конструкторы правил комбинации инициализируются с использованием конструктора ElementPair.

Существуют и другие подходы: инициализация членов с некоторым экземпляром InvalidChemicalElement или использование указателей (auto_ptr) с NULL для InvalidChemicalElement.

1 голос
/ 24 января 2010

Я думаю, вы хотите это

ChemicalElement * ce1;

Я говорю это, потому что я думаю, что он пытается запустить конструктор по умолчанию на вашем CombinationRule и, в свою очередь, должен получить ChemicalElement для ce1 и ce2 ... но я могу ошибаться.

Уверен, что путь Криля - это способ указать конструктор переменной для конкретного конструктора, НО я сказал это и только что сделал это, так что компилятор не должен конструировать ce1:)

1 голос
/ 24 января 2010

Я думаю, что вы должны поместить конструктор по умолчанию в любой класс, где вы определяете любые другие конструкторы, если вы хотите использовать объекты этого класса в любом виде массива или контейнера. Реализация конструктора по умолчанию может быть просто пустым методом / no-op.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...