gpt4 book ai didi

c++ - 是否必须定义所有静态类方法,即使未使用?

转载 作者:搜寻专家 更新时间:2023-10-31 00:08:55 24 4
gpt4 key购买 nike

所以,我遇到了一个问题,我不确定这是语言问题还是编译器/GCC 问题。

TL;DR - 我是否需要在类中定义所有静态方法,即使这些静态方法从未被调用应用程序(即无论如何都可以被链接器合法删除)?

我有一个库类,它为微 Controller 中的 UART 实现设备驱动程序。因为我不希望多个 UART 对象指向同一个资源,所以每个 UART 对象都是一个单独的对象,使用多个 GetInstance() 之一检索。方法,一个用于设备中的每个 UART 实例(UART0、UART1 等)。每个 UART 实例需要有两个 FIFO(Tx 和 Rx)用于存储。每个 FIFO 都需要由 应用程序 明确确定大小,并在 UART 对象实例化时分配(理想情况下)。所以我也有几个静态GetStorage()方法,同样,每个 UART 一次。

我已经为我的概念验证创建了一些精简代码。这是 static_instance.h:

#ifndef STATIC_INSTANCE_H_
#define STATIC_INSTANCE_H_

#ifdef __cplusplus
#include <vector>
namespace foo {
class Uart {
public:
/* Retrieve a singleton instance, using lazy static initialization. Note
* that not all instances will be present for a given device. */
static Uart& Uart1GetInstance(void);
static Uart& Uart2GetInstance(void);
static Uart& Uart3GetInstance(void);
/* Does something. */
void DoSomething(void) { ++counter; }
private:
/* Structure for the storage that each static Uart instance requires. */
struct Storage {
Storage(std::vector<char>& vector)
: my_vector_(vector) { }
std::vector<char>& my_vector_; // Buffer for data.
};
/* Instantiate object using provided register base and FIFO structures. */
Uart(int instance, Storage& storage)
: instance_(instance), storage_(storage) { }
~Uart() { }
/* Retrieves the storage required for the static Uart object instances.
* These methods are NOT implemented in static_instance.cc, but must be
* implemented in the application code, only for those Uart instances
* that are invoked in the application. */
static Storage& Uart1GetStorage(void);
static Storage& Uart2GetStorage(void);
static Storage& Uart3GetStorage(void);
int const instance_; // Instance number of this object.
Storage& storage_; // Allocated storage for this object.
int counter = 0; // Dummy counter.
};
} // namespace foo
#endif // __cplusplus

#endif

这是 static_instance.cc:

#include <static_instance.h>
namespace foo {

Uart& Uart::Uart1GetInstance(void) {
static Uart uart(1, Uart1GetStorage());
return uart;
}
Uart& Uart::Uart2GetInstance(void) {
static Uart uart(2, Uart2GetStorage());
return uart;
}
Uart& Uart::Uart3GetInstance(void) {
static Uart uart(3, Uart3GetStorage());
return uart;
}

} // namespace foo

这个想法是你只调用 GetInstance()对于您实际需要的 UART 实例,然后只定义 GetStorage()对于那个 UART 实例。 (对于这个例子,我只定义了一个缓冲区,并使用 std::vector<char> 作为替代。)此外,它留给应用程序来定义存储方法,因为每个应用程序都会有自己的要求给定的 UART 缓冲区需要很大。 (我绝对不会做的是将宏放在我的 C++ 模块中,因为,呃。)这是 main.cc 中用于实例化 UART2 的代码片段:

namespace foo {

Uart::Storage& Uart::Uart2GetStorage(void) {
static std::vector<char> rx_vector(256, 0);
static Uart::Storage storage(rx_vector);
return storage;
}
static foo::Uart& uart_ = foo::Uart::Uart2GetInstance();
void wibble(void) {
uart_.DoSomething();
}

} // namespace foo

现在,我正在使用该芯片的早期 IDE(好奇的 Kinetis Design Studio v3.2.0)开发早期的应用程序,它使用 GCC 4.8.4 并编译和链接 没有错误

但 NXP 已弃用另一个工具链 (MCUXpresso 10.0) 的 KDS,它使用 GCC 5.4.1,并使用完全相同的代码,这次我得到两个链接器错误:

./source/static_instance.o: In function 'foo::Uart::Uart1GetInstance()':
../source/static_instance.cc:5: undefined reference to 'foo::Uart::Uart1GetStorage()'
./source/static_instance.o: In function 'foo::Uart::Uart3GetInstance()':
../source/static_instance.cc:13: undefined reference to 'foo::Uart::Uart3GetStorage()'

我不确定为什么链接器会关心 GetStorage() UART1 和 UART3 的方法没有定义,因为我没有调用 GetInstance()对于我的应用程序中的 UART1 或 UART3,因此从不调用相应的 GetStorage()方法之一。

我的问题是……C++11 要求我在我的可执行文件中定义所有三种存储方法吗?也就是说,GCC 4.8.4 是否让我摆脱了一些我不应该做的事情?或者这是我需要切换的某个 GCC 5.4 选项,以允许我从类中删除未使用的静态成员?

如果答案是“无论如何你都必须定义它们”,那么我会定义它们,或者也许设计一些其他方式来允许。如果答案是“那应该没问题”,并且没有我可以在命令行上设置的选项来使 GCC 5.4 执行此操作,那么我将采取下一步并在 NXP 论坛中报告错误。谢谢。

最佳答案

TL;DR - Am I required to define all static methods within a class, even if those static methods are never called by the application

您可能需要定义此类静态方法,即使它们从未被应用程序调用。

但是,一般来说,如果这些函数不是 odr-used,您可能不需要这样做(一个定义规则)。对于静态成员函数,这等同于

A function whose name appears as a potentially-evaluated expression

区别很微妙。我希望这证明了这一点:

if(false)
function();

function 永远不会被调用,但会出现在一个可能被评估的表达式中,因此是 odr-used,因此必须被定义。


My question here is... does C++11 require me to have all three storage methods defined in my executable?

是的。它们都出现在潜在求值表达式中,因此是 ODR 使用的,因此必须定义。

I was developing an earlier application using ... GCC 4.8.4 and compiles and links with no errors.

Odr 违规具有未定义的行为,这解释了为什么您没有在其他工具链中收到错误/警告。

关于c++ - 是否必须定义所有静态类方法,即使未使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46207999/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com