簡體   English   中英

具有靜態成員的C ++注冊模式“有時”工作

[英]C++ register pattern with static member works “sometimes”

我正在嘗試在運行時實現自動類注冊(我認為該技術采用“注冊模式”的名稱)。 在下面的示例中,我將int存儲在靜態成員向量中,但目標是存儲可以在以后調用的函數指針。
我的理解是,由於下面代碼中的registeredClasses成員被聲明為static ,因此在整個程序中應該只有一個實例。 但是,事實並非如此:

classregister.h

#ifndef CLASSREGISTER_H
#define CLASSREGISTER_H

#include <vector>
#include <iostream>

class ClassRegister
{
public:
    static std::vector<int> registeredClasses; //declaration

    ClassRegister(int id) {
        std::cerr << "registering " << id << " ";
        registeredClasses.push_back(id);
        std::cerr << "new size: " << registeredClasses.size() << "\n";
    }

    //code below just for testing
    ClassRegister() {}

    static int getSize() {
        return registeredClasses.size();
    }
};

#define REGISTER_CLASS(cls) \
    static ClassRegister myClass_##cls(1);

#endif // CLASSREGISTER_H

classregister.cpp

#include "classregister.h"

std::vector<int> ClassRegister::registeredClasses; //definition

class1.h(class2.h遵循相同的模式,為簡潔起見省略)

#ifndef CLASS1_H
#define CLASS1_H

#include "classregister.h"

class Class1
{
public:
    Class1();
};

REGISTER_CLASS(Class1)

#endif // CLASS1_H

class1.cpp(class2.cpp遵循相同的模式,為簡潔起見省略)

#include "class1.h"

Class1::Class1()
{
}

main.cpp中

#include "classregister.h"
#include <iostream>

int main(int argc, char *argv[])
{
    std::cerr << "registering classes works...\n\n";

    std::cerr << "but reading from main() does not...\n";
    std::cerr << "checking size directly: " << ClassRegister::registeredClasses.size() << "\n";
    std::cerr << "checking size through function: " << ClassRegister::getSize() << "\n";
    std::cerr << "checking size on instance: " << ClassRegister().getSize() << "\n";
    std::cerr << "\n";

    std::cerr << "registration from main() uses a different register...\n";
    ClassRegister(2);
    ClassRegister(3);
    ClassRegister(4);
    std::cerr << "\n";

    std::cerr << "...which is not the one used in the header files\n";
    std::cerr << "checking size directly: " << ClassRegister::registeredClasses.size() << "\n";
    std::cerr << "checking size on instance: " << ClassRegister().getSize() << "\n";
    std::cerr << "checking size through function: " << ClassRegister::getSize() << "\n";
    std::cerr << "\n";
}

我的問題是它只能“有時”工作。 初始輸出:

registering 1 new size: 1
registering 1 new size: 2
registering classes works...

but reading from main() does not...
checking size directly: 0
checking size through function: 0
checking size on instance: 0

registration from main() uses a different register...
registering 2 new size: 1
registering 3 new size: 2
registering 4 new size: 3

...which is not the one used in the header files
checking size directly: 3
checking size on instance: 3
checking size through function: 3

我刪除了class1.cpp和class2.cpp,在頭文件中聲明了構造函數,例如。 Class1() {} 注冊根本不起作用:

//no output here
registering classes works...
//...

然后我恢復了更改,突然得到了預期的輸出:

registering 1 new size: 1
registering 1 new size: 2
registering classes works...

but reading from main() does not... //it does work this time
checking size directly: 2
checking size through function: 2
checking size on instance: 2

registration from main() uses a different register...
registering 2 new size: 3
registering 3 new size: 4
registering 4 new size: 5

...which is not the one used in the header files
checking size directly: 5
checking size on instance: 5
checking size through function: 5

我一直在研究此問題,但未能了解原因。 我的猜測是,它與編譯順序(但是注冊如何工作?)或鏈接 / 存儲持續時間有關 有人可以闡明這一點嗎?

我認為您這里需要的技巧是在ClassRegister而不是靜態數據成員中,請使用具有靜態局部函數。 有時稱為單例,盡管我不知道這是否真的是正確的術語。

代碼可能看起來像:

typedef std::vector<int> register_type;
register_type& getRegister() {
    static register_type registeredClasses; //declaration
    return registeredClasses;
}

在實現自動類注冊方案時,應注意靜態初始化順序,多線程。

刪除.cpp文件時,該文件不起作用的原因是,由於未編譯頭文件,因此沒有人知道有任何聲明。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM