Sprawdzanie czy definicja funkcji istnieje

0

Hej,
mam dwie klasy w dwóch solucjach (libka o nazwie Lib i exec o nazwie Exec)

Lib:
solucja Lib, plik lib.hpp:

class Lib
{
public:
    void test()
    {
        func();
        std::cout << "test()" << std::endl;
    }
    void func();
};

solucja Exec, plik exec.cpp:

#include <iostream>
#include "lib.hpp"

// Fragment (A)
void Lib::func()
{
    std::cout << "func()" << std::endl;
}
int main()
{
    Lib lib;
    lib.test();
    return 0;
}

To się skompiluje bez problemu. Jenak czasem może zdarzyć się, że "// Fragment (A)" nie będzie dostarczony, a mimo to chcę żeby funkcja test była wykonywalna - wystarczyłoby pominąć funkcję func() w definicji metody test(), ten kod mógłby wyglądać tak:

class Lib
{
public:
    void test()
    {
        require<func()> func();
        std::cout << "test()" << std::endl;
    }
    void func();
};

Wiem, że jest to dosyć brzydkie rozwiązanie, powinno to być bardziej obiektowe ale...
Biblioteka Lib zawiera pewne klasy, które korzystają z metody test() klasy Lib i ta metoda powinna dostosować się do ustawień Exec. To Exec powinien decydować co tam się znajdzie - taki callback, który jest znany od samego początku istnienia programu.

Jakiś pomysł?

#edit:
Ewentualnie może funkcja func() powinna zawierać jakąś domyślną definicje i jakoś nadpisywać ją?

2

Możesz zrobić własną specjalizację funkcji func() używając polimorfizmu i dziedziczenia.

#include <iostream>
#include <memory>

using namespace std;

class Lib
{
public:
    void test()
    {
        func();
        std::cout << "test()" << std::endl;
    }
    virtual void func(){ cout << "Empty function" << endl; }
};

class CustomLib : public Lib
{
    void func() override { cout << "My custom function" << endl; }
};

int main()
{
    unique_ptr<Lib> mylib = make_unique<CustomLib>();
    mylib->test();

    unique_ptr<Lib> defaultlib = make_unique<Lib>();
    defaultlib->test();

    return 0;
}
4

To jest źle zadane pytanie.
Poczytaj co to jest Problem XY i spróbuj opisać swój problem jeszcze raz.

Tak da się zmienić kod lub jego zachowanie, zależnie od dostępności innego kodu (właściwe użycie polimorfizmu, szablony).
Niestety twój opis problemu powoduje, że nie wiadomo, które rozwiązanie jest właściwe. Pewnie dostajesz błąd linkowania, a to jest już a późno na rozstrzygniecie pożądanej implementacji.

1

Zamiast polimorfizmu i dziedziczenia można by też zastosować stare dobre wskaźniki na funkcję?:

#include <iostream>

// from lib.hpp
typedef void (*MYFUN)(void);

class Lib {
    MYFUN funptr_;

  public:
    Lib(MYFUN myfun = nullptr) : funptr_(myfun){};

    void test() {
        fun();
        std::cout << "test()\n";
    }
    void fun() {
        if (funptr_ == nullptr) {
            std::cout << "default fun()\n";
        } else {
            funptr_();
        }
    }
};
// lib.hpp

// in exe.cpp
void clienfun1() { std::cout << "client fun1()\n"; }
void clienfun2() { std::cout << "client fun2()\n"; }

int main() {
    for (auto obj : {Lib(), Lib(clienfun1), Lib(clienfun2)}) {
        std::cout << "--\n";
        obj.test();
    }

    return 0;
}

Gdyby do tego dodać ładowanie DLL funkcjami LoadLibrary/GetProcAddress (dlopen/dlsym pod linuxem) to implementacje można zmieniać nawet w czasie działania programu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1