问题描述
给定一个具有一些虚函数的基类,任何人都可以想出一种方法来强制派生类在编译时覆盖一组虚函数中的一个吗?或者实现相同目的的类层次结构的替代表述?
在代码中:
struct Base
{
// Some imaginary Syntax to indicate the following are a "pure override set"
// [
virtual void function1(int) = 0;
virtual void function2(float) = 0;
// ...
// ]
};
struct Derived1 : Base {}; // ERROR not implemented
struct Derived2 : Base { void function1(int) override; }; // OK
struct Derived3 : Base { void function2(float) override; }; // OK
struct Derived4 : Base // ERROR too many implemented
{
void function1(int) override;
void function2(float) override;
};
我不确定我是否真的有一个实际的用例,但我想到了,因为我正在实施一些松散地遵循这种模式的东西,并认为这是一个值得思考的有趣问题,如果没有别的。
解决方法
不,但你可以伪造它。
Base 具有非虚拟的 float 和 int 方法,可以转发到纯虚拟 std 变体。
两个辅助类,一个 int 一个 float,实现了 std 变体之一,将两种情况都转发到纯虚拟 int 或 float 实现。
它负责处理“错误类型”的情况。
派生自一个或另一个助手,并且仅实现 int 或 float。
struct Base
{
void function1(int x) { vfunction(x); }
void function2(float x) { vfunction(x); }
virtual void vfunction(std::variant<int,float>) = 0;
};
struct Helper1:Base {
void vfunction(std::variant<int,float> v) final {
if (std::holds_alternative<int>(v))
function1_impl( std::get<int>(v) );
}
virtual void function1_impl(int x) = 0;
};
struct Helper2:Base {
void vfunction(std::variant<int,float> v) final {
if (std::holds_alternative<float>(v))
function2_impl( std::get<float>(v) );
}
virtual void function2_impl(float x) = 0;
};
struct Derived1 : Base {}; // ERROR not implemented
struct Derived2 : Helper1 { void function1_impl(int) override; }; // OK
struct Derived3 : Helper2 { void function2_impl(float) override; }; // OK
这使用了 https://en.wikipedia.org/wiki/Non-virtual_interface_pattern -- 接口包含非虚拟方法,可以覆盖其细节以使其行为不同。
如果您担心人们会覆盖 vfunction
,您可以使用私有锁技术,和/或只给它起一个像 private_implementation_detail_do_not_implement
这样的名称并信任您的代码审查过程。
或者实现相同目的的类层次结构的替代表述?
一种选择是拥有一个实现一个功能的中间基类。
struct Base
{
virtual ~Base() {};
virtual void function(int) = 0;
virtual void function(float) = 0;
};
template <typename T>
struct TBase : Base
{
virtual void function(T) override {}
};
struct Derived1 : Base {};
struct Derived2 : TBase<float> { void function(int) override {} };
struct Derived3 : TBase<int> { void function(float) override {} };
int main()
{
Derived1 d1; // ERROR. Virtual functions are not implemented
Derived2 d2; // OK.
Derived3 d3; // OK.
}
请注意,在这种方法中函数被命名为 function
,而不是 function1
和 function2
。
如果您不覆盖所有抽象虚拟方法,您的类将保持抽象。如果要实例化对象,则必须执行所有这些操作。