【问题标题】:C++ Polymorphic Data StructureC++ 多态数据结构
【发布时间】:2020-08-28 20:15:53
【问题描述】:

经过一番搜索,我还没有找到解决此问题的现有问题。如果我遗漏了什么,我深表歉意。

我有一个带有参数结构和设置器的基类。我想重新定义派生类中的 params 结构是什么样的,并通过基类指针设置它。比如下面这样的。

class A
{
public:
    struct paramsType
    {
        int a;
        int b;
    };

protected:
    paramsType params;

public:
    void setParams(const paramsType& params) { this->params = params; }
};

class B : public A
{
public:
    struct paramsType
    {
        int c;
        int d;
        int e;
    };
};

class C : public A
{
public:
    struct paramsType
    {
        int f;
    };
};

int main () {
    A* ptrB = new B();
    A* ptrC = new C();

    B::paramsType paramsB;
    paramsB.c = 0;
    paramsB.d = 1;
    paramsB.e = 2;

    C::paramsType paramsC;
    paramsC.f = 3;

    ptrB->setParams(paramsB);
    ptrC->setParams(paramsC);

    delete ptrB;
    delete ptrC;
}

我尝试将基类“setParams”设为虚拟并在派生类中重新定义它,但是当我通过基类指针调用该方法时,它的类型不兼容。

在实际用例中,B 和 C 共享大量在 A 中实现的功能。它们只是具有不同的参数集。我只能访问基类指针,但会知道对象是 B 还是 C。有没有一种优雅的方法来解决这个问题?

谢谢!

【问题讨论】:

  • 您不能以您希望的方式重新定义 C++ 中的类型(有充分的理由)。我怀疑你可能想让参数本身成为一个多态类,但是如果没有更多信息,就不可能知道这是否会解决你的问题。 A 中的常见逻辑是什么样的,它需要两组不同的参数?除了将数据传递给 A 之外,B 类和 C 类还做其他事情吗?如果您可以编辑示例代码以了解数据的使用方式,将会很有帮助。

标签: c++ class polymorphism


【解决方案1】:

您无法重新定义类型,但您可以做的是为参数提供一个公共基类。

因此您可以将A::paramsType 设为基类并从中派生B::paramsTypeC::paramsType。然后在 A 类中存储一个指向A::paramsType 的指针。这样你就可以使用一个通用的基类来传递参数。

但是,为了访问B::paramsTypeC::paramsType 的成员,您需要降低继承层次结构。您可以在成员函数中实现它。如果B::paramsType 派生自A::paramsType,它将能够访问A::paramsType 的所有公共和受保护成员; C::paramsType 也是如此。

会是这样的:

class A
{
public:
    struct paramsType
    {
        virtual ~paramsType() = default;
        int a;
        int b;
    };

protected:
    std::unique_ptr<paramsType> params;

public:
    void setParams(std::unique_ptr<paramsType> params) { this->params = std::move(params); }
};

class B : public A
{
public:
    struct paramsType : A::paramsType
    {
        int c;
        int d;
        int e;
    };

private:
    B::paramsType* getParams() { return dynamic_cast<B::paramsType*>(params.get()); }
};

一个工作版本here

【讨论】:

  • 让派生类参数从基类参数继承并通过基类参数指针连接的想法解决了我的问题。谢谢!
【解决方案2】:

在您的示例中,只需将 A 更改为

class A
{
public:
    struct paramsType
    {
        int a;
        int b;
        int c;
    };

protected:
    paramsType params;

public:
    void setParams(const paramsType& params) { this->params = params; }
};

那么 A 可以使用 paramsType::a 和 b,而 C 可以忽略 paramsType::b 和 c。

【讨论】:

  • 您好,感谢您的回复!在这种情况下,这似乎是合理的,但实际的参数集非常大,并且在任一派生类中需要新参数时都需要修改基类。
猜你喜欢
  • 2013-08-11
  • 1970-01-01
  • 2011-08-13
  • 2010-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-22
相关资源
最近更新 更多