2011-05-09 89 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