gpt4 book ai didi

c++ - 向虚方法添加具有默认值的参数

转载 作者:太空狗 更新时间:2023-10-29 20:58:50 25 4
gpt4 key购买 nike

在多层开发的背景下,核心库和客户端代码控制在完全不相关的开发团队(许多客户端开发团队)中,通过向方法添加 a 来扩展基类接口(interface)的最有效方法是什么具有默认值的新参数?

从概念上讲,我需要替换(在核心库中)这段旧代码:

struct Base
{
virtual void foo() {}
vitrual ~Base() {}
}

使用这个新代码:

struct Base
{
virtual void foo(bool b = true) {}
vitrual ~Base() {}
}

问题是这会悄无声息地破坏客户端代码,例如:

struct Derived: public Base
{
void foo() {}
}

int main()
{
Derived d;
Base &b = d;
b.foo();
}

一种解决方案是同时使用这两种方法,例如:

struct Base
{
virtual void foo(bool b) {}
virtual void foo() {foo(true);}
vitrual ~Base() {}
}

这增加了一个不必要的方法,这不是库维护的可持续方法(界面膨胀、维护成本、测试、文档等)。当然,旧方法可能会被弃用,但这意味着新的客户端代码将始终需要指定 bool 参数。

另一种解决方案可能是提供新版本的基类:

struct BaseV2: public Base
{
virtual void foo(bool b = true) {/* delegate impl. */ }
}

这增加了一个不必要的类,但至少可以方便地为客户端处理弃用。

还有哪些选择?可以做些什么来简化在核心库中引入这种微不足道的接口(interface)更改?

最佳答案

这里有几件事可能会有所帮助:

1) 使用 override 关键字会在方法现在正在隐藏而不是覆盖基类方法时发出编译器警告。例如:

struct Derived: public Base
{
void foo() override {} // Warns when Base::foo changes
};

遗憾的是,这是您必须依赖用户做的事情,而不是您可以强制执行的事情。如果您的用户经历了足够多的痛苦,他们可能会选择它。

2) 将类的接口(interface)与其实现分开——在这种情况下,实现是虚拟的,最好是私有(private)的。例如

struct Base {
void foo() { fooImpl(); }
private:
virtual void fooImpl() = 0; // Or provide a default implementation
};

struct Derived : public Base {
private:
void fooImpl() override { ... }
};

这样做的好处是您可以将默认参数添加到 foo() 而不会破坏任何内容,然后决定如何处理您代码库的其他用户。

如果您决定绝对需要将参数传递给 fooImpl() 的客户端实现者而不保留已弃用的版本,那么您可以更改其签名。使用纯虚拟,编译器将停止任何人实例化现在不再发生覆盖的类,并且您不会得到静默中断的编译。优点:没有糟糕的构建,缺点:为您的一些用户工作,即使他们不关心新功能。

或者,如果您决定将类的行为作为参数的结果委托(delegate)给不同的函数,例如fooImpl2(...) 然后在 Base::foo 中你可以测试变量是否是默认值,然后调用 fooImpl fooImpl2 根据需要。 fooImpl2 当然不需要只复制 bool 参数;您的委托(delegate)代码可以使用完全不同的参数调用它,只要您的 foo 实现可以根据旧方法签名和新参数确定要执行的操作。

沿着 fooImpl2 路线,您可以选择提供一个默认实现(优点:每个人的代码都可以毫不费力地编译和工作;缺点:您必须提供一个合理的默认实现)或使这个成为纯粹的也是虚拟的(优点:对你来说更容易;缺点:其他人的代码都会出错,即使他们不想实现你的新界面)。

这种方法的另一个好处是,现在知道您界面的所有用户都通过控制的方法进入,因此身份验证/日志记录/常见行为/授权前后的完整性检查可以所有都在一个地方完成,而不是让每个人都自己烤一半。

3) 或许可以考虑 mixins ,具体取决于您的新默认参数旨在实现的目标。从好的方面来说,这种方法为您和您的用户提供了最大的灵 active ,可以组合方法、创建新方法,并且无需在没有任何更改的情况下编写新代码。不利的一面是错误消息将难以理解,如果组织中有人不太熟悉模板编程,事情可能会变得糟糕。

关于c++ - 向虚方法添加具有默认值的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26366341/

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