0

How do I do to call a specific method present on all classes from an other (TranslationManager) class ? I simplified a lot the code. I just want to call the setTranslationText of any class from TranslationManager.

These are to take in consideration:

  1. All classes have a setTranslationText method
  2. We should call setTranslationText of any class from TranslationManager by using the pointer to the class

    class Interface
    {
       ...
       public:
         void setTranslationText(QString translatedString); 
    }
    
    class AnyOtherInterface
    {
       ...
       public:
         void setTranslationText(QString translatedString); 
    }
    
    ...
    
    …
    Translationmanager::Translationmanager(){
       AnyClass = Interface; // Pointer to Interface Class
       AnyClass->setTranslatioNText("Text");
    
       AnyClass = AnyOtherInterface; // Pointer to AnyOtherInterface Class
       AnyClass->setTranslatioNText("AnotherText");
    }
    
    
    …
    
Dardan Iljazi
  • 747
  • 1
  • 9
  • 16
  • 2
    It can't be done without that method being `virtual` in a common base and `AnyClass` being a pointer to that base. – underscore_d Apr 19 '18 at 15:22
  • Your code simplification is nonsense. The `Interface` and `AnyOtherInterface` classes share no common base class, thus there's no way to have one pointer point to them all (other than `void*`). You'll have to make the simplification work, and ensure that base classes and method signatures are exact. For example `method(QString foo)` is silly, you should have `method(const QString &foo)` – Kuba hasn't forgotten Monica Apr 19 '18 at 23:46
  • @KubaOber I really have basics knowledge on C++ (I would like to know more about it). If you have an online C++ course, be free to share – Dardan Iljazi Apr 22 '18 at 18:22

3 Answers3

5

You could use a template

template <typename T>
void setTranslationText(T* t, const QString &translatedString)
{
    t->setTranslationText(translatedString);
}

That way you wouldn't need an interface class just to inherit for this one (or however many) methods. Then the template would only compile if for a given class instantiation they had a setTranslationText method defined. The way you'd use it is

Translationmanager::Translationmanager()
{
    setTranslationText(Interface, "Text");                // Pointer to Interface Class    
    setTranslationText(AnyOtherInterface, "AnotherText"); // Pointer to AnyOtherInterface Class
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
1

Adding to Cory's answer: If you're using C strings to initialize QString, you shouldn't depend on the implicit conversion - instead, make your use case explicit:

template <typename T>
void setTranslationText(T* t, const char *translatedString) {
  t->setTranslationText(QString::fromUtf8(translatedString));
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
0

I wasn't precise about what I wanted. I finally found the best solution to my problem: callback.

Solution found on: C++ class member callback simple examples

std::vector<std::function<void(std::string,std::string)>> callbacks;

template<class T> void addTranslationText(T* const object, void(T::* const mf)(std::string,std::string)){
    using namespace std::placeholders;
    callbacks.emplace_back(std::bind(mf, object, _1, _2));
}

...

// Call callback
callbacks.at(0)(std::string("arg1"), std::string("arg2"));
Dardan Iljazi
  • 747
  • 1
  • 9
  • 16