继承的静态工厂方法返回子 Class 类型
Inherited Static Factory Method Returning Child Class Type
我有一个 Logging
class 被 LoggingString
、LoggingInt
等继承,每个都有一个 writeLog
函数接受对应类型:
class Logging {
public:
explicit Logging(const LoggingConfig& config);
...
}
class LoggingString : public Logging {
public:
using Logging::Logging;
writeLog(std::string str);
...
}
在我使用 LoggingString 的代码中,我希望能够像这样调用工厂函数:
std::unique_ptr<LoggingString> logger = LoggingString::CreateIfLoggingEnabled(LoggingConfig{...});
std::unique_ptr<LoggingInt> logger = LoggingInt::CreateIfLoggingEnabled(LoggingConfig{...});
考虑到它们都使用从基础 Logging
class 派生的相同构造函数,是否可以将此 static Logging::CreateIfLoggingEnabled
函数放在基础 class 中并且它以某种方式被 Logging
派生的 classes 继承,但返回的是 unique_ptr<LoggingDerivedClass>
?也许像这样的模板:
class Logging {
public:
explicit Logging(const LoggingConfig& config);
template<typename T> static std::unique_ptr<T> CreateIfLoggingEnabled(const LoggingConfig& config) {
...
return std::unique_ptr<T>{};
}
...
}
std::unique_ptr<LoggingString> logger = LoggingString::CreateIfLoggingEnabled<LoggingString>(LoggingConfig{...});
不确定这是否可行,而且必须指定 LoggingString
两次似乎是多余的。还有其他选择吗?
it seems redundant to have to specify LoggingString
twice.
您不必指定 LoggingString
两次(如果算上 logger
变量声明三次)。可以用Logging::
代替LoggingString::
,变量用auto
,例如:
class Logging {
public:
explicit Logging(const LoggingConfig& config);
template<typename T>
static std::unique_ptr<T> CreateIfLoggingEnabled(const LoggingConfig& config) {
...
return std::make_unique<T>(config);
}
...
};
auto logger = Logging::CreateIfLoggingEnabled<LoggingString>(LoggingConfig{...});
auto logger = Logging::CreateIfLoggingEnabled<LoggingInt>(LoggingConfig{...});
或者,您可以使用 CRTP 将派生类型传递到基础 class,例如:
template<typename Derived>
class Logging {
public:
explicit Logging(const LoggingConfig& config);
static std::unique_ptr<Derived> CreateIfLoggingEnabled(const LoggingConfig& config) {
...
return std::make_unique<Derived>(config);
}
...
};
class LoggingString : public Logging<LoggingString> {
public:
using Logging<LoggingString>::Logging;
void writeLog(std::string str);
...
};
class LoggingInt : public Logging<LoggingInt> {
public:
using Logging<LoggingInt>::Logging;
void writeLog(int i);
...
};
auto logger = LoggingString::CreateIfLoggingEnabled(LoggingConfig{...});
auto logger = LoggingInt::CreateIfLoggingEnabled(LoggingConfig{...});
我有一个 Logging
class 被 LoggingString
、LoggingInt
等继承,每个都有一个 writeLog
函数接受对应类型:
class Logging {
public:
explicit Logging(const LoggingConfig& config);
...
}
class LoggingString : public Logging {
public:
using Logging::Logging;
writeLog(std::string str);
...
}
在我使用 LoggingString 的代码中,我希望能够像这样调用工厂函数:
std::unique_ptr<LoggingString> logger = LoggingString::CreateIfLoggingEnabled(LoggingConfig{...});
std::unique_ptr<LoggingInt> logger = LoggingInt::CreateIfLoggingEnabled(LoggingConfig{...});
考虑到它们都使用从基础 Logging
class 派生的相同构造函数,是否可以将此 static Logging::CreateIfLoggingEnabled
函数放在基础 class 中并且它以某种方式被 Logging
派生的 classes 继承,但返回的是 unique_ptr<LoggingDerivedClass>
?也许像这样的模板:
class Logging {
public:
explicit Logging(const LoggingConfig& config);
template<typename T> static std::unique_ptr<T> CreateIfLoggingEnabled(const LoggingConfig& config) {
...
return std::unique_ptr<T>{};
}
...
}
std::unique_ptr<LoggingString> logger = LoggingString::CreateIfLoggingEnabled<LoggingString>(LoggingConfig{...});
不确定这是否可行,而且必须指定 LoggingString
两次似乎是多余的。还有其他选择吗?
it seems redundant to have to specify
LoggingString
twice.
您不必指定 LoggingString
两次(如果算上 logger
变量声明三次)。可以用Logging::
代替LoggingString::
,变量用auto
,例如:
class Logging {
public:
explicit Logging(const LoggingConfig& config);
template<typename T>
static std::unique_ptr<T> CreateIfLoggingEnabled(const LoggingConfig& config) {
...
return std::make_unique<T>(config);
}
...
};
auto logger = Logging::CreateIfLoggingEnabled<LoggingString>(LoggingConfig{...});
auto logger = Logging::CreateIfLoggingEnabled<LoggingInt>(LoggingConfig{...});
或者,您可以使用 CRTP 将派生类型传递到基础 class,例如:
template<typename Derived>
class Logging {
public:
explicit Logging(const LoggingConfig& config);
static std::unique_ptr<Derived> CreateIfLoggingEnabled(const LoggingConfig& config) {
...
return std::make_unique<Derived>(config);
}
...
};
class LoggingString : public Logging<LoggingString> {
public:
using Logging<LoggingString>::Logging;
void writeLog(std::string str);
...
};
class LoggingInt : public Logging<LoggingInt> {
public:
using Logging<LoggingInt>::Logging;
void writeLog(int i);
...
};
auto logger = LoggingString::CreateIfLoggingEnabled(LoggingConfig{...});
auto logger = LoggingInt::CreateIfLoggingEnabled(LoggingConfig{...});