我有一个在C 中开发的固件项目,所有驱动程序都是用类制成的,并且没有简单的修改方法。
驱动程序用于UP的内部外围,并由该类的全球实例实现;现在,我必须修改该功能,并在异常情况下允许驱动程序的"重新启动"。
驱动程序的初始化是在驱动程序的构造函数中进行的(以这种方式实现,我无法修改(,并且没有明确的方法(一种特定的方法或类似方法(重新调用该功能。因此,我需要强迫回忆班的构造师。丢失实例的所有信息不是问题,因此可以删除实例并重新重新进行。例如,代码的一部分类似于(来自MBED库(:
class SPI {
public:
SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel=NC);
void format(int bits, int mode = 0);
[.....]
~SPI()
}
在代码的其他部分中,有一个全局实例:
SPI SPI_Master(P0_9, P0_8, P0_7);
void funcA(int b){
}
因此,在函数中有一种方法可以做类似的事情:
void SPIException(){
delete SPI_Master;
SPI_Master = new SPI (P0_9, P0_8, P0_7);
}
所以要迫使构造函数被召回?
和一点澄清:
spi spi_master(p0_9,p0_8,p0_7(;
与:
完全相同spi spi_master = new spi(p0_9,p0_8,p0_7(;
?
destructor只是具有特殊名称的函数。称其为实例。〜t((。
void destroy()
{
SPI_Master.~SPI():
}
您可以通过新的位置在给定的位置强行构造一个对象。
void reinit()
{
new(&SPI_Master) SPI(/*arguments go here*/);
}
SPI SPI_Master(P0_9, P0_8, P0_7);
与 SPI SPI_Master = new SPI(P0_9, P0_8, P0_7);
在new
将指针返回到Heap对象中的指针时,最后一行不会被编译,而不是对象。同时,SPI SPI_Master(P0_9, P0_8, P0_7);
位于堆栈中。您可以阅读有关内存类型的其他信息。正确的表格将是: SPI * SPI_Master = new SPI(P0_9, P0_8, P0_7);
是的,这是您可以使用的解决方案之一。
,您提到的功能后的某个地方将按预期工作:
void SPIException(){
delete SPI_Master;
SPI_Master = new SPI (P0_9, P0_8, P0_7);
}
但它将调用使用SPI_MASTER的所有代码的更改:从SPI_Master.anyCall()
到SPI_Master->anyCall()
。
如果您无法更改行: SPI SPI_Master(P0_9, P0_8, P0_7);
您可以尝试明确调用驱动器,而不是覆盖相同的变量:
SPI_Master.~SPI();
SPI_Master = SPI(P0_9, P0_8, P0_7);
但是要小心:1(这取决于构造函数和破坏者的身体真正是什么。2(将产生您的组合商的销毁和建设顺序: - 创建新的,删除旧并分配新 - 删除旧,创建新,分配新
因此,此解决方案可能很危险。
使用global 指针与spi_master。这样:
SPI* SPI_Master;
// in some init code:
SPI_Master = new SPI .....
然后您的spiexception可以按书面形式使用。
详细说明SPD的提示:
2(显式调用破坏者并使用新的位置,以在同一内存地址构建SPI
我做了一个小样本:
#include <iostream>
struct Global {
int a1, a2;
Global(int a1, int a2): a1(a1), a2(a2)
{
std::cout << "Global::Global(): a1: " << a1 << " a2: " << a2 << 'n';
}
~Global()
{
std::cout << "Global::~Global()n";
}
Global(const Global&) = delete;
Global& operator=(const Global&) = delete;
};
std::ostream& operator<<(std::ostream &out, const Global &global)
{
return out
<< "&global: " << &global << 'n'
<< "global: global.a1: " << global.a1 << " global.a2: " << global.a2 << 'n';
}
Global global(123, 456);
int main()
{
std::cout << "Initially: " << global;
global.a1 = 321; global.a2 = 654;
std::cout << "Changed: " << global;
global.~Global();
new(&global) Global(123, 456);
std::cout << "Re-Inited: " << global;
std::cout << "Exiting...n";
}
输出:
Global::Global(): a1: 123 a2: 456
Initially: &global: 0x6013d8
global: global.a1: 123 global.a2: 456
Changed: &global: 0x6013d8
global: global.a1: 321 global.a2: 654
Global::~Global()
Global::Global(): a1: 123 a2: 456
Re-Inited: &global: 0x6013d8
global: global.a1: 123 global.a2: 456
Exiting...
Global::~Global()
coliru
实时演示请注意:
全局实例有其局限性,但可能存在,并且由于任何原因可能不会更改。(对于单例,应提及单身图案,还有其他帮助解决静态初始化顺序"惨败"(问题(?(
通常,new
创建的东西通常是在分配在堆上的内存中(即,如果不使用自定义new
(,这与在其他地方创建的静态实例相反。
放置new
可以在没有分配的情况下进行施工,即呼叫者提供的存储空间,即独立于分配存储。