开发者

How do I initialize static constant member variables in a subclass?

开发者 https://www.devze.com 2023-03-04 00:24 出处:网络
I\'m trying to make a template which can make a few different types of classes that differ mainly in the name of things, i.e. 开发者_如何学运维a resistor should output \"Resistance: 4 ohm\" where a ca

I'm trying to make a template which can make a few different types of classes that differ mainly in the name of things, i.e. 开发者_如何学运维a resistor should output "Resistance: 4 ohm" where a capacitor would output "Capacitance: 4 farad" in the same function call, without overloading. Ideally the units would just be static const std::string values.

My method was to make the base class with uninitialized

Problem here is that now I have to overload all my different types of constructors in all the subclasses.

Is there a way to just initialize the static const variables in the subclass?

Thanks


Initializing public/protected members of base class inside a derived class constructor is not allowed by current standard. One has to rely on other techniques to achieve it. There are 2 ways to address your problem.

(1) Declare virtual method returning std::string for appropriate label/values. However, this will cause unnecessary overhead. From your implementation I can make out that you want to avoid it.

(2) Use an intermediate template class, which will do it for you.

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> {
};


CRTP might be helpful:

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");


Depends on your requirements i guess:

#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;
}

output:

Resistance: 4 ohm
Capacitance: 5 farad
0

精彩评论

暂无评论...
验证码 换一张
取 消