C++ 检查编译时是否只有一个类实例

C++ 检查编译时是否只有一个类实例,c++,avr,C++,Avr,我正在为我的AVR cpu开发一个类 该类将处理所有与端口相关的操作,如Set、Read等; 构造函数看起来像: (...) public: Port(volatile uint8_t * DDR, volatile uint8_t * PORT); (...) 它是在main()的开头构造的。: 现在我想确保程序对象中没有其他具有相同参数的地方会被构造。可以肯定的是,我无法创建数组或映射来查找它并抛出异常。它必须在编译时完成。因此,基本上我想强制avr-g++检查当前项目中是否存在任

我正在为我的AVR cpu开发一个类

该类将处理所有与端口相关的操作,如Set、Read等; 构造函数看起来像:

(...)
public:
    Port(volatile uint8_t * DDR, volatile uint8_t * PORT);
(...)
它是在
main()的开头构造的。

现在我想确保程序对象中没有其他具有相同参数的地方会被构造。可以肯定的是,我无法创建数组或映射来查找它并抛出异常。它必须在编译时完成。因此,基本上我想强制avr-g++检查当前项目中是否存在任何其他端口(相同的第一个参数或相同的第二个参数)


所有函数都使用指向端口对象的指针/引用。

以下内容如何

指针的地址必须在编译时知道

template<int *p>
class Tester
{
public:
    static Tester& GetInstance()
    {
        static Tester t;
        return t;
    }

private:
    Tester() {}
};

int i;

int main()
{
    Tester<&i>& t = Tester<&i>::GetInstance();
}
模板
类测试员
{
公众:
静态测试仪&GetInstance()
{
静态测试仪t;
返回t;
}
私人:
测试器(){}
};
int i;
int main()
{
Tester&t=Tester::GetInstance();
}

这并不漂亮,但它确实完成了任务。10年的经验表明,嵌入式工作有时会像这样:/

我在MSVC下用一个简单的类测试了这一点,你必须适应你的需要,但它确实证明了这一原则

在标题中这样声明您的类:

class t
{
public:
#ifdef ALLOW_CTOR
    t(int i);
    ~t();
#endif
    int get();

private:
    int m_i;
};
然后在一个文件中添加以下行:

#define ALLOW_CTOR 1
包括头文件,将端口实例声明为文件范围变量,然后实现类、ctor、dtor、访问器等的所有类方法


如果您没有在其他源文件中放置
ALLOW\u CTOR
行,则它们仍然可以使用类中的访问器方法,但不能使用构造函数。在缺少正确的构造函数的情况下,MSVC会抱怨,因为它试图使用默认的复制构造函数,但由于参数列表不匹配,它失败了。我怀疑您正在使用的编译器会以某种方式失败,我只是不确定失败的确切原因。

如果您只需要一个类的实例,那么为什么要使用类?类的全部目的是,您可以有多个入口。只需使用全局变量和自由函数。

@Neil Kirk

如果没有为编译单元提供一个actor声明,就会导致未定义的行为,那么有办法解决这个问题

class t
{
#ifdef ALLOW_CTOR
public:
#else
private:
#endif
    t(int i);

public:
    ~t();
    int get();

private:
    int m_i;
};

将ctor在一个编译单元中标记为public,但在所有其他编译单元中标记为private,这会导致一个定义良好的错误:无法访问私有成员函数。

请阅读。在atmega上使用“new”和“delete”并不是最好的选择idea@peku33您可以使用placement new或有一个静态变量。@JoachimPileborg他不想要一个实例,每个参数值只有一个实例。好的,然后是模板。将您现在使用的参数作为构造函数作为模板参数。我确信这是未定义的行为。在C++文件的哪一节?类定义必须在源文件中一致。任何宏值都必须相同。我不知道该部分。因为对于DDR和主端口地址,将有多个具有不同地址的端口类实例。他只是试图避免端口类的两个不同实例试图引用同一硬件时会出现的问题。是否要为不了解模板概念的人详细说明一下?我主要使用C进行嵌入式编程。@Rev1.0这是一个相当高级的模板,很难简单解释。对于作为模板参数提供的每个指针地址,定义了一个新的类类型。通过将构造函数设为私有,您可以精确地控制为该指针地址创建的类类型的数量如果我决定仔细阅读的话,这是正确的方向。问题不在于是否存在构造函数:而是您引入了多个源文件观察到的不一致的定义。那是UB。
class t
{
#ifdef ALLOW_CTOR
public:
#else
private:
#endif
    t(int i);

public:
    ~t();
    int get();

private:
    int m_i;
};