如何初始化子类中的静态常量成员变量?

发布于 2024-11-05 19:49:08 字数 235 浏览 7 评论 0原文

我正在尝试制作一个模板,它可以制作几种不同类型的类,这些类主要在名称上有所不同,即电阻器应输出“电阻:4 欧姆”,而电容器应输出“电容:4 法拉”相同的函数调用,没有重载。理想情况下,单位只是 static const std::string 值。

我的方法是使用未初始化的基类,

这里的问题是现在我必须在所有子类中重载所有不同类型的构造函数。

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

谢谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤单情人 2024-11-12 19:49:08

当前标准不允许在派生类构造函数中初始化基类的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> {
};

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> {
};
无悔心 2024-11-12 19:49:08

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

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");
清风挽心 2024-11-12 19:49:08

我猜取决于你的要求:

#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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文