MajinSaha
MajinSaha

Reputation: 198

Calling non-const method of a derived class from another derived class having the same base

I have some base class and two classes derived from it. I would like to write a method for the first derived class that modifies the object's internal data by calling the already existing method of the second derived class. I want this in order to avoid making a method containing the same lines of code that I've already written for the second derived class.

Is there a safe way to do such thing? Currently, the way I do it is this:

class Base
{
protected:
    int data;
// some public methods
};

class Derived1: public Base
{
private:
    void ModifyData1() { data = 1; }
// some public methods
friend class Derived2;
};

class Derived2: public Base
{
public:
    void ModifyData2()
    {
        (static_cast<Derived1 *>((Base*)this))->Derived1::ModifyData1();
    }
};

So the way I understand it, the pointer this is implicitly converted to the base pointer (upcasting) and then the static_cast is performed on that one, to downcast to class Derived1. This modifies the object's private variable data, even though we called a method of another derived class.

The code seems to work, but I don't feel secure here, especially since the version with dynamic_cast causes segmentation fault. Thanks for any advice!

UPDATE: I'm using GCC in Linux.

Upvotes: 2

Views: 243

Answers (2)

Nhatz HK
Nhatz HK

Reputation: 42

The methods to modify the data should be placed in the same class as data. The parent class hold data, it should hold modifyData() too.

class Base {
public:
    void modifYData() { data = 1}
    // some other public methods
private:
    int data;
};

And you'll be able to do the following:

Base b;
Derived1 d1;
Derived2 d2;

b.modifyData();
d1.modifyData();
d2.modifyData();

If you want the derived classes to behave differently when modifyDtata() is called on them, make the method virtual and override it in them.

N.B: Read about encapsulation and access specifiers.

Upvotes: 0

WhiZTiM
WhiZTiM

Reputation: 21576

You invoked undefined Behavior with this code:

void ModifyData2()
{
    (static_cast<Derived1 *>(this))->ModifyData1();
}

because the this pointer is not a Derived1* neither is Derived1 a base of its value type, Derived2.


I want this in order to avoid making a method containing the same lines of code that I've already written for the second derived class.

Why don't you take that method to the base class? If you don't want to (perhaps because its not a wholistic property of all derived types) you can use an extra derived class which both Derived1 and Derived2 will inherit from.


class Base
{
protected:
    int data;
    // some public methods
};

class DerivedModifier : Base
{
protected:
    virtual void ModifyData() { data = 1; }
};

class Derived1: public DerivedModifier 
{
private:
     void ModifyData1(){
        DerivedModifier::ModifyData();
    }
};

class Derived2: public DerivedModifier 
{
public:
    void ModifyData2(){
        DerivedModifier::ModifyData();
    }
};

Upvotes: 2

Related Questions