Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在执行期间将父类转换为子类_C++_Inheritance_Casting - Fatal编程技术网

C++ 在执行期间将父类转换为子类

C++ 在执行期间将父类转换为子类,c++,inheritance,casting,C++,Inheritance,Casting,我有一个名为SavableFile的父类,以及从SavableFile继承的两个类SaveA和SaveB 它们的定义如下: class SavableFile { SavableFile(std::string _filename) : p_filename(_filename){} virtual void write() = 0; protected: std::string p_filename; } class SaveA : public SavableFil

我有一个名为
SavableFile
的父类,以及从
SavableFile
继承的两个类
SaveA
SaveB

它们的定义如下:

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; 
   }
}
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类,但我认为这是解决问题的一种不太好的方法。但我找不到一个方法来做到这一点,我也没有找到好的措辞,以便在某个地方找到帮助。。。 可能吗?
非常感谢

否,无法将现有对象转换为其他类型

另一种办法是:


这样做的缺点是总是返回动态分配的指针。为了解决这个问题,您可以添加另一层抽象:
SavableFile
将包含一个
私有FileSaver*p_FileSaver
,其中
FileSaver
是一个仅包含
virtual void write()
函数的接口。

不,不能将现有对象转换为其他类型

另一种办法是:

这样做的缺点是总是返回动态分配的指针。为了解决这个问题,您可以添加另一层抽象:
SavableFile
将包含一个
private FileSaver*p_FileSaver
,其中
FileSaver
是一个只包含
virtual void write()
函数的接口。

您可以使用工厂方法设计模式来实现这一点:

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;
}
类SavableFile{
公众:
SavableFile(std::string _filename):p_filename(_filename){}
虚空写入()=0;
受保护的:
std::字符串p_文件名;
};
类savaba:公共SavableFile{
公众:
sava(std::string _filename):SavableFile(_filename){}
void write()重写{
std::cout您可以使用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;
}
类SavableFile{
公众:
SavableFile(std::string _filename):p_filename(_filename){}
虚空写入()=0;
受保护的:
std::字符串p_文件名;
};
类savaba:公共SavableFile{
公众:
sava(std::string _filename):SavableFile(_filename){}
void write()重写{


std::你能达到想要的效果吗,但不是以你想象的方式。只要阅读多态性、虚拟函数等,即在基类中声明
virtual void write()=0
并在派生类中实现(重写)它。然后在main function
SavableFile*sf=new SaveA(…);sf->write()如果你必须这样做,那么你会遇到严重的设计问题。是的!我知道多态性,我也知道我可以做到。但是我想不用调用
新的SaveA(…)
在某个地方。只要从文件名的扩展名中扣除它。@Bцццћ您能再解释一下您的想法吗?我不太清楚。对我来说,您的问题听起来像是XY问题。()您可以实现所需的效果,但不是以您想象的方式。只需阅读多态性、虚拟函数等,即在基类中声明
virtual void write()=0
并在派生类中实现(重写)它。然后在main function
SavableFile*sf=new SaveA(…);sf->write()如果你必须这样做,那么你会遇到严重的设计问题。是的!我知道多态性,我也知道我可以做到。但是我想不用调用
新的SaveA(…)
某个地方。只需从文件名的扩展名中扣除它。@B能否再解释一下您的想法?我不确定是否能理解。对我来说,您的问题听起来像是XY问题。()从技术上讲,这种方法可能有效。但这种设计还有另一个缺点-基类“知道”从它派生的类。它阻止了所谓的“依赖倒置原则”,即“抽象不应依赖于细节”。此外,当引入新的文件格式时,还必须扩展基类。@vahancho True。我们可以将命名构造函数移动到自由函数中,这样基类就不再“知道”关于派生类。但这并不能减少问题,只是移动了它。你如何更好地设计它?恐怕,我不理解问题的本质。我猜,OP不想创建派生类的对象?如果是这样,就不可能实现他想要的。也许使用自由工厂函数将是最好的方法。如文图所说d out,这可能是一个XY问题(对此我很抱歉),我只是问是否有办法实现我想要的。但我现在明白答案显然是否定的。工厂功能似乎是“最好的”从技术上讲,这种方法可能有效。但这种设计有另一个缺点——基类“知道”派生自它的类。它阻止了所谓的“依赖倒置原则”,即“抽象不应依赖于细节”。此外,当您引入新的文件格式时,还必须扩展基类。@vahancho True。我们可以将命名构造函数移动到自由函数中,这样基类就不再“知道”关于派生类。但这并不能减少问题,只是移动了它。你如何更好地设计它?恐怕,我不理解问题的本质。我猜,OP不想创建派生类的对象?如果是这样,就不可能实现他想要的。也许使用自由工厂函数将是最好的方法。如文图所说d out,这可能是一个XY问题(对此我很抱歉),我只是问是否有办法实现我想要的。但我现在明白答案显然是否定的。工厂功能似乎是“最好的”最接近我想要的方式:)我猜你是指你们工厂其他分公司的SaveB,对吗?我猜你是指SaveB I