【问题标题】:How to configure the positioning of optional arguments to a constructor如何为构造函数配置可选参数的定位
【发布时间】:2018-05-20 17:05:06
【问题描述】:

我有一个类的构造函数如下所示:

GlslProgram(const char* vertex_shader_path, const char* fragment_shader_path, const char* tess_control_shader_path = "", const char* tess_eval_shader_path = "", const char* geom_shader_path = "");

最后三个参数都是可选的,因为""被用作默认参数。

但是,由于 C++ 不支持位置参数,如果想要调用没有tess_control_shader_pathtess_eval_shader_path 但使用geom_shader_path 的构造函数,他们必须传入两个位置"" 参数(而不是@ 987654328@ 或更清楚的信息)。

有没有一种干净或简单的方法来摆脱这种情况?换句话说:有没有办法让特定的参数放置变得不必要?

我正在查看named constructor idiom,但我不喜欢这个想法,因为在这种情况下,命名约定实际上没有意义(即GlslProgram::withGeometryShaderGlslProgram::withTesselation)似乎没有意义。

理想情况下,我会有类似的东西:

GlslProgram().vertex_path("path")
             .fragment_path("path")
             .geo_path("path")
             .tesselation_path("path");

但这里的问题是,当所有参数都完成(所有文件路径都完成)时,需要进行最后的初始化步骤,所以我不知道如何知道链中的最终“路径”是。

【问题讨论】:

  • 如果您可以“跳过”据称需要的参数,那么从技术上讲,所有参数似乎都是可选的。为什么将它们都放在构造函数中?难道你不能只将它们作为具有访问器函数的成员变量,然后在你设置了你想要的之后调用一个初始化方法吗?
  • 另一种选择是让构造函数采用一个对象,该对象具有这些路径作为具有默认值的成员
  • @amnesia 前两个参数不能跳过。

标签: c++ constructor


【解决方案1】:

有没有一种干净或简单的方法来摆脱这种情况?换句话说:有没有办法让特定的参数放置变得不必要?

我能想到的最简单的事情是为以下类设计提供可选参数的可链接设置器:

class MyClass {
    int required_param1_;
    int required_param2_;
    int optional_param1_;
    int optional_param2_;
public:
     MyClass (int required_param1, int required_param2) 
     : required_param1_(required_param1)
     , required_param2_(required_param2)
     , optional_param1_() // Use default
     , optional_param2_() // Use default
     {}
     // The 2 following statements are only for emphasis, and can be completely 
     // omitted as well, since the compiler generates these automatically.
     MyClass (const MyClass& other) = default;
     MyClass& operator=(const MyClass& other) = default;

     // Class getter / setter declarations
     int required_param1() const { return required_param1_; }
     int required_param2() const { return required_param2_; }
     int optional_param1() const { return optional_param1_; }
     MyClass& optional_param1(int value) { 
         optional_param1_ = value;
         return *this; }
     int optional_param2() const { return optional_param2_; }
     MyClass& optional_param2(int value) { 
         optional_param2_ = value;
         return *this; }
};

这允许您使用以下语法:

MyClass myClass1 = MyClass(1,2 /* <- the required parameters*/)
                          .optional_param1(5)
                          ;
MyClass myClass2 = MyClass(3,4 /* <- the required parameters*/)
                          .optional_param2(24)
                          .optional_param1(42)
                          ;

这是一个完全正常的Demo

理想情况下,我会有类似的东西:

GlslProgram().vertex_path("path")
             .fragment_path("path")
             .geo_path("path")
             .tesselation_path("path");

我的上述提议非常接近......

但这里的问题是,当所有参数都完成(所有文件路径都完成)时,需要进行最后的初始化步骤,所以我不知道如何知道链中的最终“路径”是。

... 最终初始化 步骤仍然需要并通过复制构造函数实现。虽然您可以依赖编译器的优化功能,并且 复制省略 会在那里发生。

【讨论】:

    猜你喜欢
    • 2019-02-26
    • 1970-01-01
    • 2021-03-12
    • 1970-01-01
    • 2022-01-15
    • 2016-07-26
    • 1970-01-01
    • 1970-01-01
    • 2023-01-14
    相关资源
    最近更新 更多