使用多态继承难以隔离C++代码片段的问题

huangapple go评论66阅读模式
英文:

Problem isolating a piece of c++ code using polymorphic inheritance

问题

我试图重写一段C++代码,以隔离我只想在特定对象的某些子对象中使用的代码块。

我创建了一个非常简化的版本的代码,只是为了分析问题:


class SaverInterface {
protected:
    virtual void saveData(int data) = 0;
};

class SaverImpl : public SaverInterface {
protected:
    void saveData(int data) override {
        std::cout << "data to save: " << data << std::endl;
    }
};

class ObjectA : public SaverInterface {
public:
    void save(int data) {
        saveData(data);
    }
};

class ComposedObjectA : public ObjectA, public SaverImpl {
public:
    void publicSave() {
        save(1);
    }
};

int main() {
    auto* objectA = new ComposedObjectA();
    objectA->publicSave();

    delete objectA;
    return 0;
}

我的想法是我有不同的方法来保存一些数据,我想在中间对象(ObjectA)中抽象出这个操作,调用接口的纯虚拟函数(SaverInterface),这在另一个对象(SaverImpl)中实现了。

在我的“最终”组合对象(ComposedObjectA)中,我试图从ObjectA和SaverImpl派生,认为编译器会从SaverImpl中获取saveData函数的实现,但这不起作用,编译器返回了错误消息“在'ComposedObjectA'中未实现纯虚拟方法'publicSave'”。

我对多态性相对较新(我多年来一直在编写没有这个选项的语言中),所以我可能假设了编译器无法执行的某些操作... 有人能解释一下为什么这段代码不能工作吗?

对于解决这种情况的不同方法有什么建议吗?

谢谢大家
干杯
Mix

英文:

I'm trying to rewrite a piece of code in c++ to isolate a piece of code that I would like to use only in some of the children of a particular object.

I've created a very simplified version of the code just to analyze the problem:


class SaverInterface {
protected:
    virtual void saveData(int data) = 0;
};

class SaverImpl : public SaverInterface {
protected:
    void saveData(int data) override {
        std::cout &lt;&lt; &quot;data to save: &quot; &lt;&lt; data &lt;&lt; std::endl;
    }
};

class ObjectA : public SaverInterface {
public:
    void save(int data) {
        saveData(data);
    }
};

class ComposedObjectA : public ObjectA, public SaverImpl {
public:
    void publicSave() {
        save(1);
    }
};

int main() {
    auto* objectA = new ComposedObjectA();
    objectA-&gt;publicSave();

    delete objectA;
    return 0;
}

The idea is that I have different ways of saving some data and I would like to abstract that operation in the intermediate object (ObjectA), calling the pure virtual function of the interface (SaverInterface), that is implemented in an other object (SaverImpl).

In my "final" composed object (ComposedObjectA) I've tried to derive from both the ObjectA and SaverImpl, thinking that the compiler would take the saveData function implementation from the SaverImpl, but it's not working, and the compiler gave me back the error "unimplemented pure virtual method 'publicSave' in 'ComposedObjectA'".

I'm relatively new to the polymorphism (I've written code for years in language that haven't that option) so I'm probably assuming something that the compiler cannot do...
Someone could explain me why that code couldn't work?

Any suggestion on different approach to solve the situation?

Thanks to all
Cheers
Mix

答案1

得分: 1

你遇到了一个钻石继承问题。如果你真的想继续这条路,你需要使用虚继承(所以 : public SaverInterface 应该变成 : virtual public SaverInterface 在两个地方都需要修改)。
演示

然而,在这种情况下,你真的需要继承吗?ObjectA 作为 Saver 是什么意思?它只是表示它有一个 saveData 成员函数吗?在这种情况下,为什么不使用函数指针呢?

示例:

class SaverInterface {
protected:
    using SaveDataFunction = void (*)(int);

    SaverInterface(SaveDataFunction saveData) : saveData(saveData) {}

    SaveDataFunction saveData;
};

class ObjectA : public SaverInterface {
public:
    ObjectA(SaveDataFunction saveDataFunction) : SaverInterface(saveDataFunction) {}

    void save(int data) {
        saveData(data);
    }
};

演示

你可以保留 SaverInterface 类,或者直接在 ObjectA 中实现函数指针。

英文:

You have a diamond inheritance problem. If you really want to continue down this path, you will need to use virtual inheritance (so : public SaverInterface becomes : virtual public SaverInterface in both places).
Demo

However, do you really want inheritance in this case? What does it mean for ObjectA to be a Saver? Does it just mean that is has a saveData member function? In this case, why not use a function pointer instead?

Example:

class SaverInterface {
protected:
    using SaveDataFunction = void (*)(int);

    SaverInterface(SaveDataFunction saveData) : saveData(saveData) {}

    SaveDataFunction saveData;
};

class ObjectA : public SaverInterface {
public:
    ObjectA(SaveDataFunction saveDataFunction) : SaverInterface(saveDataFunction) {}

    void save(int data) {
        saveData(data);
    }
};

Demo

You can either keep the SaverInterface class or just implement the function pointer directly in ObjectA.

huangapple
  • 本文由 发表于 2023年5月28日 20:44:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76351562.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定