2011-05-09 85 views
1

我想制作一个模板,它可以使一些不同类型的主要名称的东西不同,即电阻器应该输出“电阻:4欧姆”,电容器将输出“电容:4法拉”在相同的函数调用中,不会重载。理想情况下,单位将只是静态const std :: string值。如何初始化子类中的静态常量成员变量?

我的方法是使基类初始化

这里的问题是,现在我不得不超负荷我所有的不同类型的构造函数中的所有子类。

有没有办法在子类中初始化静态常量变量?

感谢

回答

3

初始化public/protected派生类构造函数内的基类成员是不允许按当前标准。人们必须依靠其他技术来实现它。有两种方法可以解决您的问题。

(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> { 
}; 
+1

这正是我一直在寻找的答案 - 子类构造函数是否可以访问(继承的)基类公共成员..谢谢! – 2012-05-26 19:51:53

3

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

取决于您的要求我猜:

#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