c++ - static_assert : Derive 中的某个函数“必须”隐藏 Base 的类函数
问题描述
我面临一个奇怪的罕见问题,我想隐藏 Base 类的 function B::f1(int)
。
class B{
public: void f1(int){}
public: void f1(float){}
};
class C : public B{
public: void f1(int){
//static_assert(ASSERT_that_thisFunctionHidParentFunction,"");
//some rare ugly hacky stuff
}
public: void f1(char){
//static_assert(!ASSERT_that_thisFunctionHidParentFunction,"");
}
};
一切正常;我只是担心可维护性。
我希望确保一个函数C::f1(int)
总是隐藏B::f1(int)
。
如果B::f1(int)
将来碰巧更改签名(例如更改为B::f1(int,int)
),
我想要一些编译错误来通知程序员也C::f1(int)
应该更改C::f1(int,int)
为。
在现实世界中,我有问题的功能f1
没有过载。
但是出于教育目的,如果也有过载,我想知道如何解决。(即可选)
我喜欢ASSERT_that_thisFunctionHidParentFunction
我的代码注释中的可爱解决方案。
我不介意宏。
我的糟糕解决方案
我试图 typedef 强制编译错误,但在某些情况下它不会断言失败(MCVE-coliru),因为int
它会自动转换为B::f1(float)
.
class B{
public: void f1(int,int){}
public: void f1(float){}
};
class C : public B{
public: void f1(int){
using XXX=decltype(std::declval<B>().f1(std::declval<int>()));
//static_assert(ASSERT_that_thisFunctionHidParentFunction,"");
}
public: void f1(char){
//static_assert(!ASSERT_that_thisFunctionHidParentFunction,"");
}
};
int main() {
return 0;
}
解决方案
您可以检查函数指针是否不同。
使用 MSVC 2019 和 Clang 8,这对我有用,但是 GCC 将其拒绝为“不是常量表达式”,因此可能需要不同的东西或运行时断言。不确定哪个是正确的标准。
class B {
public:
void f1(int) {}
void f2(int) {}
void f3(int) {}
void f1(float) {}
};
class C : public B {
public:
void f1(int) {}
void f1(char) {}
void f3(int) {}
};
static_assert(&B::f1 != &C::f1); // Won't work because of the overloading, can static_cast to get the overload you want
static_assert(static_cast<void(B:: *)(int)>(&B::f1) != static_cast<void(C:: *)(int)>(&C::f1));
static_assert(static_cast<void(B:: *)(int)>(&B::f2) != static_cast<void(C:: *)(int)>(&C::f2)); // static assertion failed
static_assert(&B::f3 != &C::f3); // passes, no static_cast as not overloaded
以这种方式隐藏成员函数时要非常小心,因为基类是公共的,而方法不是虚拟的。它可以很容易地进行转换,然后不调用派生函数。
C *c = ...;
B *b = c; // Implicit
b->f1(5); // Calls B::f1, not C::f1
如果可能,最好进行继承protected
或private
避免意外转换。
推荐阅读
- c# - C# - 无法调用 await Task.Delay() 函数
- r - 如何使用 R Packages:svgPanZoom 显示散点图?
- sdn - OVS中基于优先级的主动流插入和路由
- php - 插入/选择查询
- java - 将java中的对象列表转换为String键到List的映射
使用其字段之一作为键 - c - Pthreads:我的并行代码在一定数量后没有将线程传递给函数
- ruby-on-rails - 每个环境有多个 config.logger
- sapui5 - SAPUI5 将数据添加到 HanaDatabase
- tensorflow - 不将 TFLite 用于生产目的的原因是什么?
- javascript - “.addRole”的 Discord.js 问题