我有一个名为SavableFile
的父类,还有两个SaveA
继承的类SaveB
和SavableFile
。
它们的定义如下:
class SavableFile {
SavableFile(std::string _filename) : p_filename(_filename){}
virtual void write() = 0;
protected:
std::string p_filename;
}
class SaveA : public SavableFile {
SaveA(std::string _filename) : SavableFile(_filename) {}
void write() {
std::cout << "A" << std::endl;
}
}
class SaveB : public SavableFile {
SaveB(std::string _filename) : SavableFile(_filename) {}
void write() {
std::cout << "B" << std::endl;
}
}
我的问题是:是否可以创建一个SavableFile并使用文件名的扩展名将此savableFile转换为saveA或saveB?像
SavableFile(std::string _filename) : p_filename(_filename){
std::string ext = GetExtension(_filename);
//this is purely fictionnal, it's only in order to give an idea, i'm not sure if there is a way to do that, that's why i'm asking
if (ext.lower() == "a"){
*this = dynamic_cast<SaveA>(*this);
}
else {
*this = dynamic_cast<SaveB>(*this);
}
}
这样我就可以做这样的事情:
int main(int argc, char* argv[]){
SavableFile svA("foo.a");
//Here, SavableFile has been changed into SaveA class because of the constructor of SavableFile
svA->write();
//Here should be writed "A"
SavableFile svB("bar.b");
svB->write();
//Here should be writed "B"
}
我总是可以在主体中进行测试,以检查是否必须创建SaveA或SaveB类,但是我认为这不是解决问题的好方法。但是我找不到做到这一点的方法,也没有找到好的措辞来在某处寻求帮助... 可能吗? 非常感谢!
答案 0 :(得分:1)
否,您不能将现有对象转换为其他类型。
另一种方法是named constructor pattern:
print = () => {
let { state } = this.state;
qz.websocket.connect()
.then(function() {
return qz.printers.find("BillPrinter");
}).then(function(printer) {
var config = qz.configs.create(printer);
var data = [
`${state.restaurant_name}` + '\x0A',
`${state.restaurant_address}`
]
return qz.print(config, data);
});
}
这样做的缺点是总是返回动态分配的指针。为了解决这个问题,您可以添加另一层抽象:class SavableFile {
public:
static SavableFile *create(std::string _filename); // named constructor
virtual void write() = 0;
protected:
SavableFile(std::string _filename) : p_filename(_filename){} // actual constructor now protected
std::string p_filename;
};
SavableFile *SavableFile::create(std::string _filename) {
std::string ext = GetExtension(_filename);
if (ext.lower() == "a"){
return new SaveA(_filename);
}
else {
return new SaveB(_filename);
}
}
将包含一个SavableFile
,其中private FileSaver *p_filesaver
是仅包含FileSaver
函数的接口。
答案 1 :(得分:1)
您可以使用 Factory方法设计模式来做到这一点:
class Factory {
public:
static SavableFile* get(std::string _filename) {
std::string ext = GetExtension(_filename);
if (ext.lower() == "a") {
return new SaveA(_filename);
}
else {
return new SaveB(_filename);
}
return nullptr;
}
};
完整代码:
class SavableFile {
public:
SavableFile(std::string _filename) : p_filename(_filename) {}
virtual void write() = 0;
protected:
std::string p_filename;
};
class SaveA : public SavableFile {
public:
SaveA(std::string _filename) : SavableFile(_filename) {}
void write() override {
std::cout << "A" << std::endl;
}
};
class SaveB : public SavableFile {
public:
SaveB(std::string _filename) : SavableFile(_filename) {}
void write() override {
std::cout << "B" << std::endl;
}
};
class Factory {
public:
static SavableFile* get(std::string _filename) {
std::string ext = GetExtension(_filename);
if (ext.lower() == "a") {
return new SaveA(_filename);
}
else {
return new SaveB(_filename);
}
return nullptr;
}
};
int main(int argc, char* argv[]) {
SavableFile* svA = Factory::get("foo.a");
// It is better to check here if the pointer is not null.
svA->write();
SavableFile* svB = Factory::get("bar.b");
// It is better to check here if the pointer is not null.
svB->write();
delete svA;
delete svB;
return 0;
}