2

After some searching I've yet to find an existing question which address this issue. My apologies if I missed something.

I have a base class with a params structure and setter. I would like to redefine what that params structure looks like in a derived class and set it via a base class pointer. Something like the following for example.

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;
}

I've tried making the base class "setParams" virtual and redefining it in the derived class, however when I call the method via the base class pointer, it has incompatible types.

In the real use case B and C share a ton of functionality which is implemented in A. They just have different parameter sets. I only have access to a base class pointer, but will know if the object is a B or a C. Is there an elegant way to address this?

Thanks!

1
  • You can't redefine a type in C++ in the way you're hoping (for good reasons). I suspect you probably want to make the params itself a polymorphic class, but is impossible to know whether this will solve your problem without more info. What does the common logic in A look like that it would need two different sets of parameters? Do classes B and C do anything else besides passing data to A? Would be helpful if you could edit your sample code for how the data is used. Commented May 12, 2020 at 22:51

2 Answers 2

1

You can't redefine a type but what you can do is a have a common base class for the parameters.

So you could make A::paramsType a base class and derive B::paramsType and C::paramsType from that. Then store a pointer to A::paramsType in class A. That way you can use a common base class for passing in the parameters.

However, in order to access members of B::paramsType and C::paramsType you'll need to cast down the inheritance hierarchy. You could implement that in a member function. If B::paramsType is derived from A::paramsType, it will be able to access all public and protected members of A::paramsType; likewise for C::paramsType.

It will be like this:

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()); }
};

A working version here.

Sign up to request clarification or add additional context in comments.

1 Comment

The idea of having the derived class params inherit from the base class params and interfacing via a base class params pointer solved my issue. Thanks!
0

In your example, just change A to

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

protected:
    paramsType params;

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

Then A can use paramsType::a and b while C can just ignore paramsType::b and c.

1 Comment

Hello, thanks for the reply! That seems reasonable in this context, but the actual set of parameters is quite large and that would require modification of the base class any time a new parameter is required in either derived class.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.