ruslank
ruslank

Reputation: 11

Cannot define nested class member function within derived class

I have a Base class composed of another class (let's call it Component). If I inherit from the Base class, is it possible to add functionality to the Component class (assumming you can't modify the Base code)? I basically want a 'Derived::Component::foo' function.

#include <iostream>

class Base
{
    public:
        void Print() { std::cout << c.data; }

        class Component
        {
            public:
                int data;
        };
        Component c;
};

class Derived : public Base
{
    private:
        void Component::foo(int value) 
        { 
            this->data = value; 
        }
    public:
        void bar(int value)
        {
            this->c.foo(value);
        }
    };

int main() {
    Derived d;
    d.bar(4);
    d.Print();
}

This code gives the following error under G++ 4.8 on Ubuntu:

error: cannot define member function ‘Base::Component::foo’ within ‘Derived’

Upvotes: 1

Views: 4630

Answers (2)

Daniel Jour
Daniel Jour

Reputation: 16156

[..] add functionality [..] (assumming you can't modify the Base code) [..]

Depending on how the actual base class in question looks like, you could try to get by with simple subclassing of the Component:

/* using struct to have public accessibility */
struct Base {
  struct Component {
    int data;
    virtual ~Component() {} // ABSOLUTELY NECESSARY
  };
  std::unique_ptr<Component> component; // ABSOLUTELY NECESSARY

  void print(void) {
    std::cout << component->data << endl;
  }
};

/* The decorated component, with the additional functionality */
struct DecoratedComponent : public Base::Component {
  void set(int d) {
    data = d;
  }
};

Then, assuming there's someway to set the component, you need to pass in your decorated component (note: If there's state to be preserved, you could also wrap an Component instance in your decorated component class, making this a real usage of the Decorator Pattern):

Base the_base;
auto the_component = std::make_unique<DecoratedComponent>();
// Inject the decorated component
the_base.component = the_component;
the_component.set(42);
the_base.print(); // 42

This will only work if the base uses either a reference or some sort of pointer to store/access it's component. Additionally, if the base is managing the lifetime of the component, the Component must have a virtual destructor.

Upvotes: 2

where23
where23

Reputation: 513

You need to declare the foo function in the Component class. And then define it inside the Component itself:

#include <iostream>

class Base
{
public:
    void Print() { std::cout << c.data; }

    class Component
    {   
    public:
        int data;
        void foo( int value )
        { 
            data = value; 
        }
    };  

    Component c;
};

class Derived : public Base
{
private:
public:
    void bar(int value)
    {   
        c.foo(value);
    }   
};

int main() {
    Derived d;
    d.bar(4);
    d.Print();
}

Or outside of all of the classes:

#include <iostream>

class Base
{
public:
    void Print() { std::cout << c.data; }

    class Component
    {   
    public:
        int data;
        void foo( int value );
    };  

    Component c;
};

void Base::Component::foo(int value) 
{ 
    data = value; 
}

class Derived : public Base
{
private:
public:
    void bar(int value)
    {   
        c.foo(value);
    }   
};

int main() {
    Derived d;
    d.bar(4);
    d.Print();
}

Upvotes: 1

Related Questions