免责声明:对于OP,我不知道有多少种可能性,这取决于实际用例、编码约定和需求。
下面,我将针对我认为应该在问题背景下说的内容,提出我的主观选择。同样,这份清单并非详尽无遗。
在我看来,这里值得一提的主要可能性是:
-
制作一些返回设置类的工厂方法。
-
使用aggreate初始化。
-
利用生成器模式。
代码的主要特点是
Settings
只有默认构造函数。在这种情况下,您必须默认在某个地方构造它,然后传递它。
#include <string>
class Foo {
public:
struct Settings {
int opt_1;
int opt_2;
std::string opt_3;
bool opt_4;
Settings() : opt_1(0), opt_2(100), opt_3(""), opt_4(true) {}
};
Foo (const Settings &settings = Settings());
};
struct BabyFoo : public Foo
{
static Foo::Settings makeFooSettings()
{
Foo::Settings retval;
retval.opt_1=1;
retval.opt_2=22;
retval.opt_3="abcd";
retval.opt_4=false;
return retval;
}
BabyFoo() : Foo(makeFooSettings()){}
};
如果没有默认构造函数,则可以使用aggreate初始化:
它是否违背了目的?我不知道,你告诉我;)
使用aggreate初始化,可以轻松省略最后一个参数:
#include <string>
using namespace std::literals::string_literals;
class Foo {
public:
struct Settings
{
int opt_1 {0};
int opt_2 {100};
std::string opt_3{"abcd"s};
bool opt_4{true};
};
Foo(const Settings& s);
Foo();
};
struct BabyFoo : public Foo
{
BabyFoo() : Foo({8,42}){}
};
(由于以下原因,Foo有两名施工人员:
Error when using in-class initialization of non-static data member and nested class constructor
)
顺便说一句,这会变得更好,并放弃了使用C++20指定初始值设定项的下一个选项:
struct BabyFoo : public Foo
{
BabyFoo() : Foo({.opt_4=false}){} //note that this is available since C++20
};
如果您不喜欢这些解决方案中的任何一个,您可以查看生成器模式:
#include <string>
using namespace std::literals::string_literals;
class Foo {
public:
struct Settings
{
int opt_1 {0};
int opt_2 {100};
std::string opt_3{"abcd"s};
bool opt_4{true};
class Builder
{
public:
Builder& withOpt1(int o) {o1=o; return *this;}
Builder& withOpt2(int o) {o2=o; return *this;}
Builder& withOpt3(const std::string& o) {o3=o; return *this;}
Builder& withOpt1(bool o) {o4=o; return *this;}
Settings build() const {return Settings{o1,o2,o3,o4};}
private:
int o1{};
int o2{};
std::string o3{};
bool o4{};
};
};
Foo(const Settings& s);
Foo();
};
struct BabyFoo : public Foo
{
BabyFoo() : Foo(Foo::Settings::Builder().withOpt3("abc").build()){}
};
请注意,构建器可能应该直接构建Foo,而不是其设置,但同样,这取决于上下文。