Как инициализировать переменные-члены-статические константы в подклассе? - PullRequest
2 голосов
/ 09 мая 2011

Я пытаюсь создать шаблон, который может создавать несколько различных типов классов, которые отличаются главным образом по названию, то есть резистор должен выдавать «Сопротивление: 4 Ом», где конденсатор будет выводить «Емкость: 4 Фарад "в том же вызове функции, без перегрузки. В идеале единицами измерения должны быть статические значения const std :: string.

Мой метод состоял в том, чтобы сделать базовый класс с неинициализированным

Проблема здесь в том, что теперь мне приходится перегружать все мои разные типы конструкторов во всех подклассах.

Есть ли способ просто инициализировать статические переменные const в подклассе?

Спасибо

Ответы [ 3 ]

4 голосов
/ 09 мая 2011

Инициализация public/protected членов базового класса внутри конструктора производного класса не разрешена по текущему стандарту.Надо полагаться на другие методы, чтобы достичь этого.Есть 2 способа решения вашей проблемы.

(1) Объявите метод virtual, возвращающий std::string для соответствующей метки / значений.Однако это приведет к ненужным накладным расходам.Из вашей реализации я могу понять, что вы хотите этого избежать.

(2) Используйте промежуточный класс template, который сделает это за вас.

enum eValue { OHM, FARAD, AMP };  // enum to string mapping 
static const string sValue[] = { "ohm", "farad", "amp" };

// make the 'value' as reference string; to avoid making multiple copies
class Base {
  Base (const string &v) : value(v) {}
public:  const string &value; // has to be accessed using object
};

template<eValue TYPE>
struct Link : Base {  // this is an intermediate class for every derived
  Link () : Base(sValue[TYPE]) {}
};

class Resistance : public Link<OHM> {
};
3 голосов
/ 09 мая 2011

CRTP может быть полезным:

class CircuitElement
{
    virtual const std::string& getLabel() const = 0;
    virtual const std::string& getUnit() const = 0;
};

template <typename ElementType>
class CircuitElementBase : public CircuitElement
{
public:
    const std::string& getLabel() const { return ElementType::Label; }
    const std::string& getUnit() const { return ElementType::Unit; }
};

class Resistor : public CircuitElementBase<Resistor>
{
    static std::string Label, Unit;
};

std::string Resistor::Label("Resistance: ");
std::string Resistor::Unit("ohm");
2 голосов
/ 09 мая 2011

Зависит от ваших требований, я думаю:

#include <string>
#include <iostream>
#include <sstream>

struct ResistorDescriptor
{
    static const std::string type;
    static const std::string unit;
};

const std::string ResistorDescriptor::type = "Resistance";
const std::string ResistorDescriptor::unit = "ohm";

struct CapacitorDescriptor
{
    static const std::string type;
    static const std::string unit;
};

const std::string CapacitorDescriptor::type = "Capacitance";
const std::string CapacitorDescriptor::unit = "farad";

template <class T>
class Element
{
public:
    Element(int val) : value(val) {}

    std::string output()
    {
        std::stringstream s;
        s << T::type << ": " << value << " " << T::unit << std::endl;
        return s.str();
    }

private:
    int value;
};

int main(int argc, char** argv)
{
    Element<ResistorDescriptor> resistor(4);
    Element<CapacitorDescriptor> capacitor(5);

    std::cout << resistor.output() << capacitor.output() << std::flush;

    return 0;
}

вывод:

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