0

One way to add methods to a class without changing it is with inheritance (e.g., Add a method to existing C++ class in other file). However, this solution causes a problem to the toy program below:

#include <vector>       

class c_A {
    public:
        std::vector<int> v;
        c_A one_element(void) {
            c_A res; 
            res.v = v;
            res.v.resize(1);
            return res;
        };
};

class c_Aext : public c_A { 
   // Methods here
};

int main () {
 
   c_Aext Aext;
   Aext.v = {0, 1, 2};
   c_Aext B = Aext.one_element(); // The problem
   return 0;
};

What are the possible solutions to this problem? Casting? Removing the class c_Aext and integrating its methods in C_A? ...

Medical physicist
  • 2,510
  • 4
  • 34
  • 51

3 Answers3

1

You can add your own one_element() wrapper along with a c_Aext constructor that'll take a c_A:

class c_Aext : public c_A { 
public:
    c_Aext() : c_A() { } // just call parent's default
    c_Aext(const c_A c) : c_A(c) { } // call parent's copy

    c_Aext one_element() { return c_Aext(c_A::one_element()); }
};

Full compiled example here: https://ideone.com/auSoH4

scohe001
  • 15,110
  • 2
  • 31
  • 51
  • Yes, but this solution doesn't escalate well when *c_A* has many methods. – Medical physicist Dec 23 '20 at 18:50
  • @Medical you'll only need to add one line for each of `c_A`'s functions that look like this. If `c_A` has anything less than 30 functions like this, I can't imagine it'd be too bad. – scohe001 Dec 23 '20 at 18:53
0

Another option using smart pointers and casting:

#include <vector>     
#include <memory>  

class c_A {
    public:
        std::vector<int> v;
        std::shared_ptr<c_A> one_element(void) {
            std::shared_ptr<c_A> res = std::make_shared<c_A>(); 
            res->v = v;
            res->v.resize(1);
            return res;
        };
};

class c_Aext : public c_A { 
   // Methods here
};

int main () {
 
   c_Aext Aext;
   Aext.v = {0, 1, 2};
   std::shared_ptr<c_Aext> B = std::static_pointer_cast<c_Aext>(Aext.one_element()); 
   return 0;
};
Medical physicist
  • 2,510
  • 4
  • 34
  • 51
0

In addition you may take a look for CRTP

If you modify your example you can get something like:

#include <vector>
template < typename T>
class A: public T
{
    public:
        std::vector<int> v;

        A<T> one_element() {
            A<T> res;
            res.v = v;
            res.v.resize(1);
            return res;
        };
};

class Aext {
    public:
        void AnyOtherMethod(){ std::cout << "Other" << std::endl; }
};

int main () {
    A< Aext> aext;
    aext.v = {0, 1, 2}; 
    A< Aext> b = aext.one_element(); // The problem
    b.AnyOtherMethod();

    return 0;
}

Above code is not full CRTP as it has no cast operations to access the extension class and so on. See the linked wikepedia page for much more examples how you can use it to "configure" your class on the fly and access data between such classes in your "reverse" hierarchy. I would not copy paste all the stuff here.

Maybe CRTP fits your design goal or not, but in hope it gives you another idea.

Klaus
  • 24,205
  • 7
  • 58
  • 113