2015-09-30 6 views
1

Я видел Is it possible to replace a method at runtime in C/C++?, но я кое-что новичок в C++, и поэтому пока не вижу, как (и если) это применимо к моему делу, поэтому я хотел бы попробовать спросить с моим примером.Замена метода базового класса C++?

В приведенном ниже примере, предположим, что классы MyBase, A1 и A2, из какой-нибудь библиотеки, и я их использую в моей main:

// g++ -std=c++11 -o test.exe test.cpp 

#include <iostream> 

using namespace std; 

class MyBase { 
public: 
    MyBase() { } 
    ~MyBase() { } 
    int getBaseVal(int inval) { 
    return inval + 5; 
    } 
}; 

class A1 : public MyBase { 
public: 
    A1() : MyBase() { } 
    ~A1() { } 
    int getVal(int inval) { 
    return getBaseVal(inval) + 10; 
    } 
}; 

class A2 : public A1 { 
public: 
    A2() : A1() { } 
    ~A2() { } 
    int getVal(int inval) { 
    return getBaseVal(inval) + 20; 
    } 
}; 


int main() { 
    A1 _a1 = A1(); A2 _a2 = A2(); 
    cout << "A1 for 10: " << _a1.getVal(10) << endl; 
    cout << "A2 for 10: " << _a2.getVal(10) << endl; 
    return 0; 
} 

Теперь, скажем, я хотел бы оставить это библиотека была нетронутой, но я обнаружил ошибку в MyBase::getBaseVal, так как возвращаемое правое значение должно быть inval + 6; вместо заданного inval + 5;. Итак, ничего сложного, но нужен вход для входных аргументов метода.

Так что у меня есть возможность, чтобы определить новую функцию, скажем:

int getNewBaseVal(int inval) { 
    return inval + 6; 
} 

.. а потом как-то "заменить" старый MyBase::getBaseVal:

  • На уровне класса (т.е. is, MyBase будет «исправлен»), так что все последующие экземпляры A1 и A2 в конечном итоге будут использовать getNewBaseVal, когда вызывается их getVal s;
  • На уровне объекта, так что только конкретный экземпляр объекта, скажем, A1 как объекта (например, _a1), в конечном итоге будет использовать getNewBaseVal, когда вызывается его getVal;

... путем написания кода в начале функции main?

+4

Итак, вы полностью прочитали предыдущие вопросы и ответы о том, можно ли заменить метод ......... тогда вы снова задали тот же вопрос? –

+0

@LightnessRacesinOrbit - ну да; как один, я не уверен, применим ли здесь квалификатор «runtime» (я хотел бы сделать «патч» один раз при запуске, а не изменять его динамически, возможно, для этого есть непринужденные критерии?); во-вторых, если полиморфизм является ответом, у меня нет идеи, как я буду распространять только «MyBase», не имея необходимости также расширять «A1», «A2» и целую цепочку наследования, я хотел бы избежать, и главная причина моего вопроса. – sdaau

+3

Ну, длинный и короткий, что вы не можете. Возьмите автора библиотеки, чтобы исправить ошибку, и создайте свою собственную разветвленную и фиксированную версию. –

ответ

4

Долгий и короткий оттого, что вы не можете; по крайней мере, не в пределах заданных ограничений (которые исключают различные субоптимальные хаки, такие как Андрей!).

Получить автора библиотеки, чтобы исправить ошибку, и создать свою собственную разветвленную и фиксированную версию.

0

Я хотел бы предложить вам создать класс адаптера и использовать его в качестве базового класса для A и B

class MyBaseAdaptor: public MyBase 
{ 
    using MyBase::MyBase; // Inherit constructors 

public: 
    int getBaseVal(int inval) // Hide the old method 
    { 
     // your code here 
    } 
}; 

Но это лучше исправить библиотеку.

+1

Спасибо, @AndreyNasonov, но тогда классы 'A1',' A2' еще не знали о 'MyBaseAdaptor', если я их не перекодирую, поэтому они наследуют от' MyBaseAdaptor'; это верно? – sdaau

+1

Да, 'class A1: public MyBaseAdaptor' –

+1

@AndreyNasonov: OP указывает, совершенно правильно, что он должен будет сделать это для _each и каждого класса в дереве наследования, что нежелательно. Вы не ответили на вопрос по заданным ограничениям. –

Смежные вопросы